react-calendar
Advanced tools
Comparing version 2.19.2 to 3.0.0-beta
{ | ||
"name": "react-calendar", | ||
"version": "2.19.2", | ||
"version": "3.0.0-beta", | ||
"description": "Ultimate calendar for your React app.", | ||
"main": "dist/entry.js", | ||
"main": "dist/umd/entry.js", | ||
"module": "dist/esm/entry.js", | ||
"source": "src/entry.js", | ||
"types": "./index.d.ts", | ||
"sideEffects": false, | ||
"scripts": { | ||
"build": "yarn build-js && yarn copy-styles && yarn build-styles && yarn copy-types", | ||
"build-js": "babel src -d dist --ignore **/__tests__,**/**/__tests__", | ||
"build-styles": "lessc ./dist/Calendar.less ./dist/Calendar.css", | ||
"build": "yarn build-js-all && yarn copy-styles && yarn build-styles", | ||
"build-js-all": "yarn build-js-esm && yarn build-js-umd", | ||
"build-js-esm": "BABEL_ENV=production-esm babel src -d dist/esm --ignore **/*.spec.js,**/*.spec.jsx", | ||
"build-js-umd": "BABEL_ENV=production-umd babel src -d dist/umd --ignore **/*.spec.js,**/*.spec.jsx", | ||
"build-styles": "yarn build-styles-esm && yarn build-styles-umd", | ||
"build-styles-esm": "lessc ./dist/esm/Calendar.less ./dist/esm/Calendar.css", | ||
"build-styles-umd": "lessc ./dist/umd/Calendar.less ./dist/umd/Calendar.css", | ||
"clean": "rimraf dist", | ||
"copy-styles": "node ./copy-styles.js", | ||
"copy-types": "node ./copy-types.js", | ||
"jest": "jest", | ||
@@ -44,2 +48,5 @@ "jest-coverage": "jest --coverage", | ||
{ | ||
"name": "Alberto Carreras" | ||
}, | ||
{ | ||
"name": "Andriy Kuzyk" | ||
@@ -70,6 +77,6 @@ }, | ||
"dependencies": { | ||
"@wojtekmaj/date-utils": "^1.0.0", | ||
"get-user-locale": "^1.2.0", | ||
"merge-class-names": "^1.1.1", | ||
"prop-types": "^15.6.0", | ||
"react-lifecycles-compat": "^3.0.4" | ||
"prop-types": "^15.6.0" | ||
}, | ||
@@ -97,7 +104,7 @@ "devDependencies": { | ||
"react-test-renderer": "^16.7.0", | ||
"rimraf": "^2.6.2" | ||
"rimraf": "^3.0.0" | ||
}, | ||
"peerDependencies": { | ||
"react": ">=15.5", | ||
"react-dom": ">=15.5" | ||
"react": ">=16.3", | ||
"react-dom": ">=16.3" | ||
}, | ||
@@ -107,3 +114,2 @@ "files": [ | ||
"README.md", | ||
"index.d.ts", | ||
"dist/", | ||
@@ -110,0 +116,0 @@ "src/" |
@@ -27,2 +27,8 @@ [![npm](https://img.shields.io/npm/v/react-calendar.svg)](https://www.npmjs.com/package/react-calendar) ![downloads](https://img.shields.io/npm/dt/react-calendar.svg) ![build](https://img.shields.io/travis/wojtekmaj/react-calendar/master.svg) ![dependencies](https://img.shields.io/david/wojtekmaj/react-calendar.svg) ![dev dependencies](https://img.shields.io/david/dev/wojtekmaj/react-calendar.svg) [![tested with jest](https://img.shields.io/badge/tested_with-jest-99424f.svg)](https://github.com/facebook/jest) | ||
## Before you continue | ||
React-Calendar is under constant development. This documentation is written for React-Calendar 3.x branch. If you want to see documentation for other versions of React-Calendar, use dropdown on top of GitHub page to switch to an appropriate tag. Here are quick links to the newest docs from each branch: | ||
* [v2.x](https://github.com/wojtekmaj/react-pdf/blob/v2.x/README.md) | ||
## Getting started | ||
@@ -76,4 +82,14 @@ | ||
If you don't want to use default React-Calendar styling to build upon it, you can import React-Calendar by using `import Calendar from 'react-calendar/dist/entry.nostyle';` instead. | ||
If you don't want to use default React-Calendar styling to build upon it, you can import React-Calendar by using: | ||
```js | ||
// using ES6 modules | ||
import Calendar from 'react-calendar/dist/esm/entry.nostyle'; | ||
// using CommonJS modules | ||
import Calendar from 'react-calendar/dist/umd/entry.nostyle'; | ||
``` | ||
instead. | ||
## User guide | ||
@@ -89,8 +105,12 @@ | ||
|----|----|----|----| | ||
|activeStartDate|The beginning of a period that shall be displayed by default when no value is given.|(today)|`new Date(2017, 0, 1)`| | ||
|activeStartDate|The beginning of a period that shall be displayed. If you wish to use React-Calendar in an uncontrolled way, use `defaultActiveStartDate` instead.|(today)|`new Date(2017, 0, 1)`| | ||
|calendarType|Type of calendar that should be used. Can be `"ISO 8601"`, `"US"`, `"Arabic"`, or `"Hebrew"`. Setting to `"US"` or `"Hebrew"` will change the first day of the week to Sunday. Setting to `"Arabic"` will change the first day of the week to Saturday. Setting to `"Arabic"` or `"Hebrew"` will make weekends appear on Friday to Saturday.|Type of calendar most commonly used in a given locale|`"ISO 8601"`| | ||
|className|Class name(s) that will be added along with `"react-calendar"` to the main React-Calendar `<div>` element.|n/a|<ul><li>String: `"class1 class2"`</li><li>Array of strings: `["class1", "class2 class3"]`</li></ul>| | ||
|defaultActiveStartDate|The beginning of a period that shall be displayed by default. If you wish to use React-Calendar in a controlled way, use `activeStartDate` instead.|(today)|`new Date(2017, 0, 1)`| | ||
|defaultValue|Calendar value that shall be selected initially. If you wish to use React-Calendar in a controlled way, use `value` instead.|n/a|<ul><li>Date: `new Date()`</li><li>An array of dates: `[new Date(2017, 0, 1), new Date(2017, 7, 1)]`| | ||
|defaultView|Determines which calendar view shall be opened initially. Does not disable navigation. Can be `"month"`, `"year"`, `"decade"` or `"century"`. If you wish to use React-Calendar in a controlled way, use `view` instead.|The most detailed view allowed|`"year"`| | ||
|formatMonth|Function called to override default formatting of month names. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'MMM')`| | ||
|formatMonthYear|Function called to override default formatting of month and year in the top navigation section. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'MMMM YYYY')`| | ||
|formatShortWeekday|Function called to override default formatting of weekday names. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'dd')`| | ||
|formatYear|Function called to override default formatting of year in the top navigation section. Can be used to use your own formatting function.|(default formatter)|`(locale, date) => formatDate(date, 'YYYY')`| | ||
|locale|Locale that should be used by the calendar. Can be any [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag).|User's browser settings|`"hu-HU"`| | ||
@@ -107,4 +127,5 @@ |maxDate|Maximum date that the user can select. Periods partially overlapped by maxDate will also be selectable, although React-Calendar will ensure that no later date is selected.|n/a|Date: `new Date()`| | ||
|next2Label|Content of the "next on higher level" button on the navigation pane.|`"»"`|<ul><li>String: `"»"`</li><li>React element: `<DoubleNextIcon />`</li></ul>| | ||
|onActiveDateChange|Function called when the user navigates from one view to another using previous/next button.|n/a|`({ activeStartDate, view }) => alert('Changed view to: ', activeStartDate, view)`| | ||
|onActiveStartDateChange|Function called when the user navigates from one view to another using previous/next button.|n/a|`({ activeStartDate, view }) => alert('Changed view to: ', activeStartDate, view)`| | ||
|onChange|Function called when the user clicks an item (day on month view, month on year view and so on) on the most detailed view available.|n/a|`(value) => alert('New date is: ', value)`| | ||
|onViewChange|Function called when the user navigates from one view to another using drill up button or by clicking a tile.|n/a|`({ activeStartDate, view }) => alert('New view is: ', view)`| | ||
|onClickDay|Function called when the user clicks a day.|n/a|`(value) => alert('Clicked day: ', value)`| | ||
@@ -122,2 +143,3 @@ |onClickDecade|Function called when the user clicks a decade.|n/a|`(value) => alert('Clicked decade: ', value)`| | ||
|returnValue|Which dates shall be passed by the calendar to the onChange function and onClick{Period} functions. Can be `"start"`, `"end"` or `"range"`. The latter will cause an array with start and end values to be passed.|`"start"`|`"range"`| | ||
|showDoubleView|Whether to show two months/years/… at a time instead of one. Forces `showFixedNumberOfWeeks` prop to be `true`.|`false`|`true`| | ||
|showFixedNumberOfWeeks|Whether to always show fixed number of weeks (6). Forces `showNeighboringMonth` prop to be `true`.|`false`|`true`| | ||
@@ -131,4 +153,4 @@ |showNavigation|Whether a navigation bar with arrows and title shall be rendered.|`true`|`false`| | ||
|tileDisabled|Pass a function to determine if a certain day should be displayed as disabled.|n/a|<ul><li>Function: `({activeStartDate, date, view }) => date.getDay() === 0`</li></ul>| | ||
|value|Calendar value.|n/a|<ul><li>Date: `new Date()`</li><li>An array of dates: `[new Date(2017, 0, 1), new Date(2017, 7, 1)]`| | ||
|view|Determines which calendar view shall be opened initially. Does not disable navigation. Can be `"month"`, `"year"`, `"decade"` or `"century"`.|The most detailed view allowed|`"year"`| | ||
|value|Calendar value. If you wish to use React-Calendar in an uncontrolled way, use `defaultValue` instead.|n/a|<ul><li>Date: `new Date()`</li><li>An array of dates: `[new Date(2017, 0, 1), new Date(2017, 7, 1)]`| | ||
|view|Determines which calendar view shall be opened. Does not disable navigation. Can be `"month"`, `"year"`, `"decade"` or `"century"`. If you wish to use React-Calendar in an uncontrolled way, use `defaultView` instead.|The most detailed view allowed|`"year"`| | ||
@@ -135,0 +157,0 @@ ### MonthView, YearView, DecadeView, CenturyView |
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { polyfill } from 'react-lifecycles-compat'; | ||
import mergeClassNames from 'merge-class-names'; | ||
@@ -12,5 +11,7 @@ | ||
import { getBegin, getEnd, getValueRange } from './shared/dates'; | ||
import { | ||
isCalendarType, isClassName, isMaxDate, isMinDate, isValue, | ||
getBegin, getBeginNext, getEnd, getValueRange, | ||
} from './shared/dates'; | ||
import { | ||
isCalendarType, isClassName, isMaxDate, isMinDate, isValue, isView, | ||
} from './shared/propTypes'; | ||
@@ -23,8 +24,2 @@ import { between, callIfDefined, mergeFunctions } from './shared/utils'; | ||
const datesAreDifferent = (date1, date2) => ( | ||
(date1 && !date2) | ||
|| (!date1 && date2) | ||
|| (date1 && date2 && date1.getTime() !== date2.getTime()) | ||
); | ||
/** | ||
@@ -150,4 +145,4 @@ * Returns views array with disallowed values cut off. | ||
const valueFrom = ( | ||
activeStartDate, | ||
getDetailValueFrom(value, minDate, maxDate, maxDetail) | ||
|| activeStartDate | ||
|| new Date() | ||
@@ -158,61 +153,55 @@ ); | ||
const isSingleValue = value => value && [].concat(value).length === 1; | ||
export default class Calendar extends Component { | ||
static getDerivedStateFromProps(nextProps, prevState) { | ||
const { | ||
minDate, maxDate, minDetail, maxDetail, | ||
} = nextProps; | ||
state = { | ||
/* eslint-disable react/destructuring-assignment */ | ||
activeStartDate: this.props.defaultActiveStartDate || getActiveStartDate(this.props), | ||
view: this.props.defaultView, | ||
value: this.props.defaultValue, | ||
/* eslint-enable react/destructuring-assignment */ | ||
}; | ||
const nextState = {}; | ||
get activeStartDate() { | ||
const { activeStartDate: activeStartDateProps } = this.props; | ||
const { activeStartDate: activeStartDateState } = this.state; | ||
/** | ||
* If the next activeStartDate is different from the current one, update | ||
* activeStartDate (for display) and activeStartDateProps (for future comparisons) | ||
*/ | ||
const nextActiveStartDate = getActiveStartDate(nextProps); | ||
if (datesAreDifferent(nextActiveStartDate, prevState.activeStartDateProps)) { | ||
nextState.activeStartDate = nextActiveStartDate; | ||
nextState.activeStartDateProps = nextActiveStartDate; | ||
} | ||
return activeStartDateProps || activeStartDateState; | ||
} | ||
/** | ||
* If the next view is different from the current one, and the previously set view is not | ||
* valid based on minDetail and maxDetail, get a new one. | ||
*/ | ||
const nextView = getView(nextProps.view, minDetail, maxDetail); | ||
if (nextView !== prevState.viewProps && !isViewAllowed(prevState.view, minDetail, maxDetail)) { | ||
nextState.view = nextView; | ||
nextState.viewProps = nextView; | ||
} | ||
get value() { | ||
const { selectRange, value: valueProps } = this.props; | ||
const { value: valueState } = this.state; | ||
/** | ||
* If the next value is different from the current one (with an exception of situation in | ||
* which values provided are limited by minDate and maxDate so that the dates are the same), | ||
* get a new one. | ||
*/ | ||
const values = [nextProps.value, prevState.valueProps]; | ||
if ( | ||
nextState.view // Allowed view changed | ||
|| datesAreDifferent( | ||
...values.map(value => getValueFrom(value, minDate, maxDate, maxDetail)), | ||
) | ||
|| datesAreDifferent( | ||
...values.map(value => getValueTo(value, minDate, maxDate, maxDetail)), | ||
) | ||
) { | ||
nextState.value = nextProps.value; | ||
nextState.valueProps = nextProps.value; | ||
// In the middle of range selection, use value from state | ||
if (selectRange && isSingleValue(valueState)) { | ||
return valueState; | ||
} | ||
if (!nextProps.selectRange && prevState.hover) { | ||
nextState.hover = null; | ||
} | ||
return valueProps || valueState; | ||
} | ||
return nextState; | ||
get valueType() { | ||
const { maxDetail } = this.props; | ||
return getValueType(maxDetail); | ||
} | ||
state = {}; | ||
get view() { | ||
const { minDetail, maxDetail, view: viewProps } = this.props; | ||
const { view: viewState } = this.state; | ||
return getView(viewProps || viewState, minDetail, maxDetail); | ||
} | ||
get hover() { | ||
const { selectRange } = this.props; | ||
const { hover } = this.state; | ||
return selectRange ? hover : null; | ||
} | ||
get drillDownAvailable() { | ||
const { view } = this; | ||
const { maxDetail, minDetail } = this.props; | ||
const { view } = this.state; | ||
@@ -225,4 +214,4 @@ const views = getLimitedViews(minDetail, maxDetail); | ||
get drillUpAvailable() { | ||
const { view } = this; | ||
const { maxDetail, minDetail } = this.props; | ||
const { view } = this.state; | ||
@@ -234,8 +223,2 @@ const views = getLimitedViews(minDetail, maxDetail); | ||
get valueType() { | ||
const { maxDetail } = this.props; | ||
return getValueType(maxDetail); | ||
} | ||
/** | ||
@@ -269,8 +252,8 @@ * Gets current value in a desired format. | ||
setActiveStartDate = (activeStartDate) => { | ||
const { onActiveDateChange } = this.props; | ||
const { onActiveStartDateChange } = this.props; | ||
this.setState({ activeStartDate }, () => { | ||
const { view } = this.state; | ||
const { view } = this; | ||
callIfDefined(onActiveDateChange, { | ||
callIfDefined(onActiveStartDateChange, { | ||
activeStartDate, | ||
@@ -282,3 +265,21 @@ view, | ||
drillDown = (activeStartDate) => { | ||
/** | ||
* Called when the user uses navigation buttons. | ||
*/ | ||
setActiveStartDateAndView = (activeStartDate, view) => { | ||
const { onActiveStartDateChange, onViewChange } = this.props; | ||
this.setState({ activeStartDate, view }, () => { | ||
callIfDefined(onActiveStartDateChange, { | ||
activeStartDate, | ||
view, | ||
}); | ||
callIfDefined(onViewChange, { | ||
activeStartDate, | ||
view, | ||
}); | ||
}); | ||
} | ||
drillDown = (nextActiveStartDate) => { | ||
if (!this.drillDownAvailable) { | ||
@@ -288,2 +289,3 @@ return; | ||
const { view } = this; | ||
const { maxDetail, minDetail, onDrillDown } = this.props; | ||
@@ -293,15 +295,9 @@ | ||
this.setState((prevState) => { | ||
const nextView = views[views.indexOf(prevState.view) + 1]; | ||
return { | ||
activeStartDate, | ||
view: nextView, | ||
}; | ||
}, () => { | ||
const { view } = this.state; | ||
const nextView = views[views.indexOf(view) + 1]; | ||
callIfDefined(onDrillDown, { | ||
activeStartDate, | ||
view, | ||
}); | ||
this.setActiveStartDateAndView(nextActiveStartDate, nextView); | ||
callIfDefined(onDrillDown, { | ||
activeStartDate: nextActiveStartDate, | ||
view: nextView, | ||
}); | ||
@@ -315,2 +311,3 @@ } | ||
const { activeStartDate, view } = this; | ||
const { maxDetail, minDetail, onDrillUp } = this.props; | ||
@@ -320,17 +317,10 @@ | ||
this.setState((prevState) => { | ||
const nextView = views[views.indexOf(prevState.view) - 1]; | ||
const activeStartDate = getBegin(nextView, prevState.activeStartDate); | ||
const nextView = views[views.indexOf(view) - 1]; | ||
const nextActiveStartDate = getBegin(nextView, activeStartDate); | ||
return { | ||
activeStartDate, | ||
view: nextView, | ||
}; | ||
}, () => { | ||
const { activeStartDate, view } = this.state; | ||
this.setActiveStartDateAndView(nextActiveStartDate, nextView); | ||
callIfDefined(onDrillUp, { | ||
activeStartDate, | ||
view, | ||
}); | ||
callIfDefined(onDrillUp, { | ||
activeStartDate: nextActiveStartDate, | ||
view: nextView, | ||
}); | ||
@@ -345,8 +335,6 @@ } | ||
if (selectRange) { | ||
const { value: previousValue } = this.state; | ||
const { value: previousValue } = this; | ||
// Range selection turned on | ||
if ( | ||
!previousValue | ||
|| [].concat(previousValue).length !== 1 // 0 or 2 - either way we're starting a new array | ||
) { | ||
if (!isSingleValue(previousValue)) { | ||
// Value has 0 or 2 elements - either way we're starting a new array | ||
// First value | ||
@@ -382,4 +370,11 @@ nextValue = getBegin(this.valueType, value); | ||
renderContent() { | ||
renderContent(next) { | ||
const { | ||
activeStartDate: currentActiveStartDate, | ||
onMouseOver, | ||
valueType, | ||
value, | ||
view, | ||
} = this; | ||
const { | ||
calendarType, | ||
@@ -395,7 +390,10 @@ locale, | ||
} = this.props; | ||
const { | ||
activeStartDate, hover, value, view, | ||
} = this.state; | ||
const { onMouseOver, valueType } = this; | ||
const { hover } = this; | ||
const activeStartDate = ( | ||
next | ||
? getBeginNext(view, currentActiveStartDate) | ||
: currentActiveStartDate | ||
); | ||
const commonProps = { | ||
@@ -419,6 +417,7 @@ activeStartDate, | ||
case 'century': { | ||
const { onClickDecade } = this.props; | ||
const { formatYear, onClickDecade } = this.props; | ||
return ( | ||
<CenturyView | ||
formatYear={formatYear} | ||
onClick={mergeFunctions(clickAction, onClickDecade)} | ||
@@ -430,6 +429,7 @@ {...commonProps} | ||
case 'decade': { | ||
const { onClickYear } = this.props; | ||
const { formatYear, onClickYear } = this.props; | ||
return ( | ||
<DecadeView | ||
formatYear={formatYear} | ||
onClick={mergeFunctions(clickAction, onClickYear)} | ||
@@ -456,2 +456,3 @@ {...commonProps} | ||
onClickWeekNumber, | ||
showDoubleView, | ||
showFixedNumberOfWeeks, | ||
@@ -470,3 +471,3 @@ showNeighboringMonth, | ||
onMouseLeave={onMouseLeave} | ||
showFixedNumberOfWeeks={showFixedNumberOfWeeks} | ||
showFixedNumberOfWeeks={showFixedNumberOfWeeks || showDoubleView} | ||
showNeighboringMonth={showNeighboringMonth} | ||
@@ -490,4 +491,6 @@ showWeekNumbers={showWeekNumbers} | ||
const { activeStartDate, view } = this; | ||
const { | ||
formatMonthYear, | ||
formatYear, | ||
locale, | ||
@@ -508,4 +511,4 @@ maxDate, | ||
prevLabel, | ||
showDoubleView, | ||
} = this.props; | ||
const { activeStartDate, view } = this.state; | ||
@@ -517,2 +520,3 @@ return ( | ||
formatMonthYear={formatMonthYear} | ||
formatYear={formatYear} | ||
locale={locale} | ||
@@ -532,2 +536,3 @@ maxDate={maxDate} | ||
setActiveStartDate={this.setActiveStartDate} | ||
showDoubleView={showDoubleView} | ||
view={view} | ||
@@ -540,5 +545,4 @@ views={getLimitedViews(minDetail, maxDetail)} | ||
render() { | ||
const { className, selectRange } = this.props; | ||
const { value } = this.state; | ||
const { onMouseLeave } = this; | ||
const { className, selectRange, showDoubleView } = this.props; | ||
const { onMouseLeave, value } = this; | ||
const valueArray = [].concat(value); | ||
@@ -551,2 +555,3 @@ | ||
selectRange && valueArray.length === 1 && `${baseClassName}--selectRange`, | ||
showDoubleView && `${baseClassName}--doubleView`, | ||
className, | ||
@@ -562,2 +567,3 @@ )} | ||
{this.renderContent()} | ||
{showDoubleView && this.renderContent(true)} | ||
</div> | ||
@@ -575,12 +581,21 @@ </div> | ||
showNeighboringMonth: true, | ||
view: 'month', | ||
}; | ||
const isActiveStartDate = PropTypes.instanceOf(Date); | ||
const isLooseValue = PropTypes.oneOfType([ | ||
PropTypes.string, | ||
isValue, | ||
]); | ||
Calendar.propTypes = { | ||
activeStartDate: PropTypes.instanceOf(Date), | ||
activeStartDate: isActiveStartDate, | ||
calendarType: isCalendarType, | ||
className: isClassName, | ||
defaultActiveStartDate: isActiveStartDate, | ||
defaultValue: isLooseValue, | ||
defaultView: isView, | ||
formatMonth: PropTypes.func, | ||
formatMonthYear: PropTypes.func, | ||
formatShortWeekday: PropTypes.func, | ||
formatYear: PropTypes.func, | ||
locale: PropTypes.string, | ||
@@ -597,3 +612,3 @@ maxDate: isMaxDate, | ||
nextLabel: PropTypes.node, | ||
onActiveDateChange: PropTypes.func, | ||
onActiveStartDateChange: PropTypes.func, | ||
onChange: PropTypes.func, | ||
@@ -607,2 +622,3 @@ onClickDay: PropTypes.func, | ||
onDrillUp: PropTypes.func, | ||
onViewChange: PropTypes.func, | ||
prev2AriaLabel: PropTypes.string, | ||
@@ -615,2 +631,3 @@ prev2Label: PropTypes.node, | ||
selectRange: PropTypes.bool, | ||
showDoubleView: PropTypes.bool, | ||
showFixedNumberOfWeeks: PropTypes.bool, | ||
@@ -629,9 +646,4 @@ showNavigation: PropTypes.bool, | ||
tileDisabled: PropTypes.func, | ||
value: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
isValue, | ||
]), | ||
view: PropTypes.oneOf(allViews), | ||
value: isLooseValue, | ||
view: isView, | ||
}; | ||
polyfill(Calendar); |
@@ -13,5 +13,7 @@ import React from 'react'; | ||
getEndPrevious2, | ||
getYear, | ||
} from '../shared/dates'; | ||
import { formatMonthYear as defaultFormatMonthYear } from '../shared/dateFormatter'; | ||
import { | ||
formatMonthYear as defaultFormatMonthYear, | ||
formatYear as defaultFormatYear, | ||
} from '../shared/dateFormatter'; | ||
import { isView, isViews } from '../shared/propTypes'; | ||
@@ -22,19 +24,21 @@ | ||
export default function Navigation({ | ||
activeStartDate: date, | ||
activeStartDate, | ||
drillUp, | ||
formatMonthYear, | ||
formatMonthYear = defaultFormatMonthYear, | ||
formatYear = defaultFormatYear, | ||
locale, | ||
maxDate, | ||
minDate, | ||
navigationAriaLabel, | ||
navigationAriaLabel = '', | ||
navigationLabel, | ||
next2AriaLabel, | ||
next2Label, | ||
nextAriaLabel, | ||
nextLabel, | ||
prev2AriaLabel, | ||
prev2Label, | ||
prevAriaLabel, | ||
prevLabel, | ||
next2AriaLabel = '', | ||
next2Label = '»', | ||
nextAriaLabel = '', | ||
nextLabel = '›', | ||
prev2AriaLabel = '', | ||
prev2Label = '«', | ||
prevAriaLabel = '', | ||
prevLabel = '‹', | ||
setActiveStartDate, | ||
showDoubleView, | ||
view, | ||
@@ -46,6 +50,9 @@ views, | ||
const previousActiveStartDate = getBeginPrevious(view, date); | ||
const previousActiveStartDate2 = shouldShowPrevNext2Buttons && getBeginPrevious2(view, date); | ||
const nextActiveStartDate = getBeginNext(view, date); | ||
const nextActiveStartDate2 = shouldShowPrevNext2Buttons && getBeginNext2(view, date); | ||
const previousActiveStartDate = getBeginPrevious(view, activeStartDate); | ||
const previousActiveStartDate2 = ( | ||
shouldShowPrevNext2Buttons | ||
&& getBeginPrevious2(view, activeStartDate) | ||
); | ||
const nextActiveStartDate = getBeginNext(view, activeStartDate); | ||
const nextActiveStartDate2 = shouldShowPrevNext2Buttons && getBeginNext2(view, activeStartDate); | ||
@@ -56,3 +63,3 @@ const prevButtonDisabled = (() => { | ||
} | ||
const previousActiveEndDate = getEndPrevious(view, date); | ||
const previousActiveEndDate = getEndPrevious(view, activeStartDate); | ||
return minDate && minDate >= previousActiveEndDate; | ||
@@ -65,3 +72,3 @@ })(); | ||
} | ||
const previousActiveEndDate = getEndPrevious2(view, date); | ||
const previousActiveEndDate = getEndPrevious2(view, activeStartDate); | ||
return minDate && minDate >= previousActiveEndDate; | ||
@@ -94,17 +101,25 @@ })(); | ||
const label = (() => { | ||
switch (view) { | ||
case 'century': | ||
return getCenturyLabel(date); | ||
case 'decade': | ||
return getDecadeLabel(date); | ||
case 'year': | ||
return getYear(date); | ||
case 'month': | ||
return formatMonthYear(locale, date); | ||
default: | ||
throw new Error(`Invalid view: ${view}.`); | ||
} | ||
})(); | ||
function renderLabel(date) { | ||
const label = (() => { | ||
switch (view) { | ||
case 'century': | ||
return getCenturyLabel(locale, formatYear, date); | ||
case 'decade': | ||
return getDecadeLabel(locale, formatYear, date); | ||
case 'year': | ||
return formatYear(locale, date); | ||
case 'month': | ||
return formatMonthYear(locale, date); | ||
default: | ||
throw new Error(`Invalid view: ${view}.`); | ||
} | ||
})(); | ||
return ( | ||
navigationLabel | ||
? navigationLabel({ date, view, label }) | ||
: label | ||
); | ||
} | ||
return ( | ||
@@ -143,5 +158,11 @@ <div | ||
> | ||
{navigationLabel | ||
? navigationLabel({ date, view, label }) | ||
: label} | ||
{renderLabel(activeStartDate)} | ||
{showDoubleView && ( | ||
<> | ||
{' '} | ||
– | ||
{' '} | ||
{renderLabel(nextActiveStartDate)} | ||
</> | ||
)} | ||
</button> | ||
@@ -172,15 +193,2 @@ <button | ||
Navigation.defaultProps = { | ||
formatMonthYear: defaultFormatMonthYear, | ||
navigationAriaLabel: '', | ||
next2AriaLabel: '', | ||
next2Label: '»', | ||
nextAriaLabel: '', | ||
nextLabel: '›', | ||
prev2AriaLabel: '', | ||
prev2Label: '«', | ||
prevAriaLabel: '', | ||
prevLabel: '‹', | ||
}; | ||
Navigation.propTypes = { | ||
@@ -190,2 +198,3 @@ activeStartDate: PropTypes.instanceOf(Date).isRequired, | ||
formatMonthYear: PropTypes.func, | ||
formatYear: PropTypes.func, | ||
locale: PropTypes.string, | ||
@@ -205,4 +214,5 @@ maxDate: PropTypes.instanceOf(Date), | ||
setActiveStartDate: PropTypes.func.isRequired, | ||
showDoubleView: PropTypes.bool, | ||
view: isView.isRequired, | ||
views: isViews.isRequired, | ||
}; |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { getDecadeStart, getDecadeEnd } from '@wojtekmaj/date-utils'; | ||
import Tile from '../Tile'; | ||
import { getBeginOfDecade, getDecadeLabel, getEndOfDecade } from '../shared/dates'; | ||
import { getDecadeLabel } from '../shared/dates'; | ||
import { formatYear as defaultFormatYear } from '../shared/dateFormatter'; | ||
import { tileProps } from '../shared/propTypes'; | ||
@@ -11,3 +13,9 @@ | ||
export default function Decade({ classes, point, ...otherProps }) { | ||
export default function Decade({ | ||
classes, | ||
date, | ||
formatYear = defaultFormatYear, | ||
locale, | ||
...otherProps | ||
}) { | ||
return ( | ||
@@ -17,7 +25,9 @@ <Tile | ||
classes={[].concat(classes, className)} | ||
maxDateTransform={getEndOfDecade} | ||
minDateTransform={getBeginOfDecade} | ||
date={date} | ||
locale={locale} | ||
maxDateTransform={getDecadeEnd} | ||
minDateTransform={getDecadeStart} | ||
view="century" | ||
> | ||
{getDecadeLabel(point)} | ||
{getDecadeLabel(locale, formatYear, date)} | ||
</Tile> | ||
@@ -29,3 +39,3 @@ ); | ||
...tileProps, | ||
point: PropTypes.number.isRequired, | ||
formatYear: PropTypes.func, | ||
}; |
import React from 'react'; | ||
import { getDecadeStart } from '@wojtekmaj/date-utils'; | ||
@@ -6,6 +7,3 @@ import TileGroup from '../TileGroup'; | ||
import { | ||
getBeginOfDecade, | ||
getBeginOfCenturyYear, | ||
} from '../shared/dates'; | ||
import { getBeginOfCenturyYear } from '../shared/dates'; | ||
import { tileGroupProps } from '../shared/propTypes'; | ||
@@ -22,3 +20,3 @@ | ||
className="react-calendar__century-view__decades" | ||
dateTransform={getBeginOfDecade} | ||
dateTransform={getDecadeStart} | ||
dateType="decade" | ||
@@ -25,0 +23,0 @@ end={end} |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { getYearStart, getYearEnd } from '@wojtekmaj/date-utils'; | ||
import Tile from '../Tile'; | ||
import { getBeginOfYear, getEndOfYear } from '../shared/dates'; | ||
import { formatYear as defaultFormatYear } from '../shared/dateFormatter'; | ||
import { tileProps } from '../shared/propTypes'; | ||
@@ -11,3 +12,9 @@ | ||
export default function Year({ classes, point, ...otherProps }) { | ||
export default function Year({ | ||
classes, | ||
date, | ||
formatYear = defaultFormatYear, | ||
locale, | ||
...otherProps | ||
}) { | ||
return ( | ||
@@ -17,7 +24,9 @@ <Tile | ||
classes={[].concat(classes, className)} | ||
maxDateTransform={getEndOfYear} | ||
minDateTransform={getBeginOfYear} | ||
date={date} | ||
locale={locale} | ||
maxDateTransform={getYearEnd} | ||
minDateTransform={getYearStart} | ||
view="decade" | ||
> | ||
{point} | ||
{formatYear(locale, date)} | ||
</Tile> | ||
@@ -29,3 +38,3 @@ ); | ||
...tileProps, | ||
point: PropTypes.number.isRequired, | ||
formatYear: PropTypes.func, | ||
}; |
@@ -8,2 +8,3 @@ import React from 'react'; | ||
import { CALENDAR_TYPES } from './shared/const'; | ||
import { | ||
@@ -16,2 +17,53 @@ isCalendarType, | ||
function getCalendarTypeFromLocale(locale) { | ||
switch (locale) { | ||
case 'en-CA': | ||
case 'en-US': | ||
case 'es-AR': | ||
case 'es-BO': | ||
case 'es-CL': | ||
case 'es-CO': | ||
case 'es-CR': | ||
case 'es-DO': | ||
case 'es-EC': | ||
case 'es-GT': | ||
case 'es-HN': | ||
case 'es-MX': | ||
case 'es-NI': | ||
case 'es-PA': | ||
case 'es-PE': | ||
case 'es-PR': | ||
case 'es-SV': | ||
case 'es-VE': | ||
case 'pt-BR': | ||
return CALENDAR_TYPES.US; | ||
// ar-LB, ar-MA intentionally missing | ||
case 'ar': | ||
case 'ar-AE': | ||
case 'ar-BH': | ||
case 'ar-DZ': | ||
case 'ar-EG': | ||
case 'ar-IQ': | ||
case 'ar-JO': | ||
case 'ar-KW': | ||
case 'ar-LY': | ||
case 'ar-OM': | ||
case 'ar-QA': | ||
case 'ar-SA': | ||
case 'ar-SD': | ||
case 'ar-SY': | ||
case 'ar-YE': | ||
case 'dv': | ||
case 'dv-MV': | ||
case 'ps': | ||
case 'ps-AR': | ||
return CALENDAR_TYPES.ARABIC; | ||
case 'he': | ||
case 'he-IL': | ||
return CALENDAR_TYPES.HEBREW; | ||
default: | ||
return CALENDAR_TYPES.ISO_8601; | ||
} | ||
} | ||
export default function MonthView(props) { | ||
@@ -32,57 +84,4 @@ const { | ||
const calendarType = (() => { | ||
if (calendarTypeProps) { | ||
return calendarTypeProps; | ||
} | ||
const calendarType = calendarTypeProps || getCalendarTypeFromLocale(locale); | ||
switch (locale) { | ||
case 'en-CA': | ||
case 'en-US': | ||
case 'es-AR': | ||
case 'es-BO': | ||
case 'es-CL': | ||
case 'es-CO': | ||
case 'es-CR': | ||
case 'es-DO': | ||
case 'es-EC': | ||
case 'es-GT': | ||
case 'es-HN': | ||
case 'es-MX': | ||
case 'es-NI': | ||
case 'es-PA': | ||
case 'es-PE': | ||
case 'es-PR': | ||
case 'es-SV': | ||
case 'es-VE': | ||
case 'pt-BR': | ||
return 'US'; | ||
// ar-LB, ar-MA intentionally missing | ||
case 'ar': | ||
case 'ar-AE': | ||
case 'ar-BH': | ||
case 'ar-DZ': | ||
case 'ar-EG': | ||
case 'ar-IQ': | ||
case 'ar-JO': | ||
case 'ar-KW': | ||
case 'ar-LY': | ||
case 'ar-OM': | ||
case 'ar-QA': | ||
case 'ar-SA': | ||
case 'ar-SD': | ||
case 'ar-SY': | ||
case 'ar-YE': | ||
case 'dv': | ||
case 'dv-MV': | ||
case 'ps': | ||
case 'ps-AR': | ||
return 'Arabic'; | ||
case 'he': | ||
case 'he-IL': | ||
return 'Hebrew'; | ||
default: | ||
return 'ISO 8601'; | ||
} | ||
})(); | ||
function renderWeekdays() { | ||
@@ -89,0 +88,0 @@ return ( |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { getDate, getDayStart, getDayEnd } from '@wojtekmaj/date-utils'; | ||
import Tile from '../Tile'; | ||
import { | ||
getBeginOfDay, | ||
getDay, | ||
getEndOfDay, | ||
isWeekend, | ||
} from '../shared/dates'; | ||
import { isWeekend } from '../shared/dates'; | ||
import { formatLongDate } from '../shared/dateFormatter'; | ||
@@ -35,7 +31,7 @@ import { tileProps } from '../shared/propTypes'; | ||
formatAbbr={formatLongDate} | ||
maxDateTransform={getEndOfDay} | ||
minDateTransform={getBeginOfDay} | ||
maxDateTransform={getDayEnd} | ||
minDateTransform={getDayStart} | ||
view="month" | ||
> | ||
{getDay(date)} | ||
{getDate(date)} | ||
</Tile> | ||
@@ -42,0 +38,0 @@ ); |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
getYear, | ||
getMonth, | ||
getDaysInMonth, | ||
} from '@wojtekmaj/date-utils'; | ||
@@ -7,8 +12,3 @@ import TileGroup from '../TileGroup'; | ||
import { | ||
getDayOfWeek, | ||
getDaysInMonth, | ||
getMonthIndex, | ||
getYear, | ||
} from '../shared/dates'; | ||
import { getDayOfWeek } from '../shared/dates'; | ||
import { isCalendarType, tileGroupProps } from '../shared/propTypes'; | ||
@@ -28,3 +28,3 @@ | ||
const year = getYear(activeStartDate); | ||
const monthIndex = getMonthIndex(activeStartDate); | ||
const monthIndex = getMonth(activeStartDate); | ||
@@ -31,0 +31,0 @@ const hasFixedNumberOfWeeks = showFixedNumberOfWeeks || showNeighboringMonth; |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
getYear, | ||
getMonth, | ||
getMonthStart, | ||
} from '@wojtekmaj/date-utils'; | ||
import Flex from '../Flex'; | ||
import { | ||
getBeginOfMonth, | ||
getDayOfWeek, | ||
getMonthIndex, | ||
getYear, | ||
} from '../shared/dates'; | ||
import { getDayOfWeek } from '../shared/dates'; | ||
import { formatWeekday, formatShortWeekday as defaultFormatShortWeekday } from '../shared/dateFormatter'; | ||
@@ -18,3 +18,3 @@ import { isCalendarType } from '../shared/propTypes'; | ||
calendarType, | ||
formatShortWeekday, | ||
formatShortWeekday = defaultFormatShortWeekday, | ||
locale, | ||
@@ -25,5 +25,5 @@ onMouseLeave, | ||
const anyDate = new Date(); | ||
const beginOfMonth = getBeginOfMonth(anyDate); | ||
const beginOfMonth = getMonthStart(anyDate); | ||
const year = getYear(beginOfMonth); | ||
const monthIndex = getMonthIndex(beginOfMonth); | ||
const monthIndex = getMonth(beginOfMonth); | ||
@@ -63,6 +63,2 @@ const weekdays = []; | ||
Weekdays.defaultProps = { | ||
formatShortWeekday: defaultFormatShortWeekday, | ||
}; | ||
Weekdays.propTypes = { | ||
@@ -69,0 +65,0 @@ calendarType: isCalendarType.isRequired, |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { | ||
getYear, | ||
getMonth, | ||
getDate, | ||
getDaysInMonth, | ||
} from '@wojtekmaj/date-utils'; | ||
@@ -9,8 +15,4 @@ import WeekNumber from './WeekNumber'; | ||
getBeginOfWeek, | ||
getDay, | ||
getDayOfWeek, | ||
getDaysInMonth, | ||
getMonthIndex, | ||
getWeekNumber, | ||
getYear, | ||
} from '../shared/dates'; | ||
@@ -42,4 +44,4 @@ import { isCalendarType } from '../shared/propTypes'; | ||
const year = getYear(activeStartDate); | ||
const monthIndex = getMonthIndex(activeStartDate); | ||
const day = getDay(activeStartDate); | ||
const monthIndex = getMonth(activeStartDate); | ||
const day = getDate(activeStartDate); | ||
@@ -46,0 +48,0 @@ const result = []; |
@@ -27,12 +27,14 @@ import getUserLocale from 'get-user-locale'; | ||
const formatLongDateOptions = { day: 'numeric', month: 'long', year: 'numeric' }; | ||
const formatMonthOptions = { month: 'long' }; | ||
const formatMonthYearOptions = { month: 'long', year: 'numeric' }; | ||
const formatMonthOptions = { month: 'long' }; | ||
const formatYearOptions = { year: 'numeric' }; | ||
const formatShortWeekdayOptions = { weekday: 'short' }; | ||
const formatWeekdayOptions = { weekday: 'long' }; | ||
const formatShortWeekdayOptions = { weekday: 'short' }; | ||
export const formatDate = getSafeFormatter(formatDateOptions); | ||
export const formatLongDate = getSafeFormatter(formatLongDateOptions); | ||
export const formatMonth = getSafeFormatter(formatMonthOptions); | ||
export const formatMonthYear = getSafeFormatter(formatMonthYearOptions); | ||
export const formatMonth = getSafeFormatter(formatMonthOptions); | ||
export const formatYear = getSafeFormatter(formatYearOptions); | ||
export const formatShortWeekday = getSafeFormatter(formatShortWeekdayOptions); | ||
export const formatWeekday = getSafeFormatter(formatWeekdayOptions); | ||
export const formatShortWeekday = getSafeFormatter(formatShortWeekdayOptions); |
@@ -1,43 +0,58 @@ | ||
const [ | ||
// eslint-disable-next-line no-unused-vars | ||
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, | ||
] = [...Array(7)].map((el, index) => index); | ||
import { | ||
getYear, | ||
getMonth as getMonthIndex, | ||
/* Simple getters - getting a property of a given point in time */ | ||
getCenturyStart, | ||
getPreviousCenturyStart, | ||
getNextCenturyStart, | ||
getCenturyEnd, | ||
getPreviousCenturyEnd, | ||
getCenturyRange, | ||
export function getYear(date) { | ||
if (date instanceof Date) { | ||
return date.getFullYear(); | ||
} | ||
getDecadeStart, | ||
getPreviousDecadeStart, | ||
getNextDecadeStart, | ||
getDecadeEnd, | ||
getPreviousDecadeEnd, | ||
getDecadeRange, | ||
if (typeof date === 'number') { | ||
return date; | ||
} | ||
getYearStart, | ||
getPreviousYearStart, | ||
getNextYearStart, | ||
getYearEnd, | ||
getPreviousYearEnd, | ||
getYearRange, | ||
const year = parseInt(date, 10); | ||
getMonthStart, | ||
getPreviousMonthStart, | ||
getNextMonthStart, | ||
getMonthEnd, | ||
getPreviousMonthEnd, | ||
getMonthRange, | ||
if (typeof date === 'string' && !isNaN(year)) { | ||
return year; | ||
} | ||
getDayStart, | ||
getDayEnd, | ||
getDayRange, | ||
} from '@wojtekmaj/date-utils'; | ||
throw new Error(`Failed to get year from date: ${date}.`); | ||
} | ||
import { CALENDAR_TYPES, WEEKDAYS } from './const'; | ||
import { formatYear as defaultFormatYear } from './dateFormatter'; | ||
export function getMonth(date) { return date.getMonth() + 1; } | ||
const SUNDAY = WEEKDAYS[0]; | ||
const FRIDAY = WEEKDAYS[5]; | ||
const SATURDAY = WEEKDAYS[6]; | ||
export function getMonthIndex(date) { return date.getMonth(); } | ||
/* Simple getters - getting a property of a given point in time */ | ||
export function getDay(date) { return date.getDate(); } | ||
export function getDayOfWeek(date, calendarType = 'ISO 8601') { | ||
export function getDayOfWeek(date, calendarType = CALENDAR_TYPES.ISO_8601) { | ||
const weekday = date.getDay(); | ||
switch (calendarType) { | ||
case 'ISO 8601': | ||
case CALENDAR_TYPES.ISO_8601: | ||
// Shifts days of the week so that Monday is 0, Sunday is 6 | ||
return (weekday + 6) % 7; | ||
case 'Arabic': | ||
case CALENDAR_TYPES.ARABIC: | ||
return (weekday + 1) % 7; | ||
case 'Hebrew': | ||
case 'US': | ||
case CALENDAR_TYPES.HEBREW: | ||
case CALENDAR_TYPES.US: | ||
return weekday; | ||
@@ -49,148 +64,24 @@ default: | ||
/* Complex getters - getting a property somehow related to a given point in time */ | ||
export function getBeginOfCenturyYear(date) { | ||
const year = getYear(date) - 1; | ||
return year + (-year % 100) + 1; | ||
} | ||
export function getBeginOfCentury(date) { | ||
const beginOfCenturyYear = getBeginOfCenturyYear(date); | ||
return new Date(beginOfCenturyYear, 0, 1); | ||
} | ||
export function getEndOfCentury(date) { | ||
const beginOfCenturyYear = getBeginOfCenturyYear(date); | ||
return new Date(beginOfCenturyYear + 100, 0, 1, 0, 0, 0, -1); | ||
} | ||
export function getCenturyRange(date) { | ||
return [ | ||
getBeginOfCentury(date), | ||
getEndOfCentury(date), | ||
]; | ||
} | ||
export function getBeginOfPreviousCentury(date) { | ||
const previousCenturyYear = getYear(date) - 100; | ||
return getBeginOfCentury(previousCenturyYear); | ||
} | ||
export function getEndOfPreviousCentury(date) { | ||
const previousCenturyYear = getYear(date) - 100; | ||
return getEndOfCentury(previousCenturyYear); | ||
} | ||
export function getBeginOfNextCentury(date) { | ||
const nextCenturyYear = getYear(date) + 100; | ||
return getBeginOfCentury(nextCenturyYear); | ||
} | ||
export function getBeginOfDecadeYear(date) { | ||
const year = getYear(date) - 1; | ||
return year + (-year % 10) + 1; | ||
} | ||
export function getBeginOfDecade(date) { | ||
const beginOfDecadeYear = getBeginOfDecadeYear(date); | ||
return new Date(beginOfDecadeYear, 0, 1); | ||
} | ||
export function getEndOfDecade(date) { | ||
const beginOfDecadeYear = getBeginOfDecadeYear(date); | ||
return new Date(beginOfDecadeYear + 10, 0, 1, 0, 0, 0, -1); | ||
} | ||
export function getDecadeRange(date) { | ||
return [ | ||
getBeginOfDecade(date), | ||
getEndOfDecade(date), | ||
]; | ||
} | ||
export function getBeginOfPreviousDecade(date, offset = 10) { | ||
const previousDecadeYear = getBeginOfDecadeYear(date) - offset; | ||
return getBeginOfDecade(previousDecadeYear); | ||
} | ||
export function getEndOfPreviousDecade(date, offset = 10) { | ||
const previousDecadeYear = getBeginOfDecadeYear(date) - offset; | ||
return getEndOfDecade(previousDecadeYear); | ||
} | ||
export function getBeginOfNextDecade(date, offset = 10) { | ||
const nextDecadeYear = getBeginOfDecadeYear(date) + offset; | ||
return getBeginOfDecade(nextDecadeYear); | ||
} | ||
/** | ||
* Returns the beginning of a given year. | ||
* | ||
* @param {Date} date Date. | ||
* Century | ||
*/ | ||
export function getBeginOfYear(date) { | ||
const year = getYear(date); | ||
return new Date(year, 0, 1); | ||
} | ||
/** | ||
* Returns the end of a given year. | ||
* | ||
* @param {Date} date Date. | ||
*/ | ||
export function getEndOfYear(date) { | ||
const year = getYear(date); | ||
return new Date(year + 1, 0, 1, 0, 0, 0, -1); | ||
export function getBeginOfCenturyYear(date) { | ||
const beginOfCentury = getCenturyStart(date); | ||
return getYear(beginOfCentury); | ||
} | ||
/** | ||
* Returns an array with the beginning and the end of a given year. | ||
* | ||
* @param {Date} date Date. | ||
* Decade | ||
*/ | ||
export function getYearRange(date) { | ||
return [ | ||
getBeginOfYear(date), | ||
getEndOfYear(date), | ||
]; | ||
export function getBeginOfDecadeYear(date) { | ||
const beginOfDecade = getDecadeStart(date); | ||
return getYear(beginOfDecade); | ||
} | ||
export function getBeginOfPreviousYear(date, offset = 1) { | ||
const previousYear = getYear(date) - offset; | ||
return getBeginOfYear(previousYear); | ||
} | ||
export function getEndOfPreviousYear(date, offset = 1) { | ||
const previousYear = getYear(date) - offset; | ||
return getEndOfYear(previousYear); | ||
} | ||
export function getBeginOfNextYear(date, offset = 1) { | ||
const nextYear = getYear(date) + offset; | ||
return getBeginOfYear(nextYear); | ||
} | ||
/** | ||
* Returns the beginning of a given month. | ||
* | ||
* @param {Date} date Date. | ||
* Week | ||
*/ | ||
export function getBeginOfMonth(date) { | ||
const year = getYear(date); | ||
const monthIndex = getMonthIndex(date); | ||
return new Date(year, monthIndex, 1); | ||
} | ||
/** | ||
* Returns the end of a given month. | ||
* | ||
* @param {Date} date Date. | ||
*/ | ||
export function getEndOfMonth(date) { | ||
const year = getYear(date); | ||
const monthIndex = getMonthIndex(date); | ||
return new Date(year, monthIndex + 1, 1, 0, 0, 0, -1); | ||
} | ||
/** | ||
* Returns the beginning of a given week. | ||
@@ -201,3 +92,3 @@ * | ||
*/ | ||
export function getBeginOfWeek(date, calendarType = 'ISO 8601') { | ||
export function getBeginOfWeek(date, calendarType = CALENDAR_TYPES.ISO_8601) { | ||
const year = getYear(date); | ||
@@ -210,61 +101,2 @@ const monthIndex = getMonthIndex(date); | ||
/** | ||
* Returns an array with the beginning and the end of a given month. | ||
* | ||
* @param {Date} date Date. | ||
*/ | ||
export function getMonthRange(date) { | ||
return [ | ||
getBeginOfMonth(date), | ||
getEndOfMonth(date), | ||
]; | ||
} | ||
function getDifferentMonth(date, offset) { | ||
const year = getYear(date); | ||
const previousMonthIndex = getMonthIndex(date) + offset; | ||
return new Date(year, previousMonthIndex, 1); | ||
} | ||
export function getBeginOfPreviousMonth(date, offset = 1) { | ||
const previousMonth = getDifferentMonth(date, -offset); | ||
return getBeginOfMonth(previousMonth); | ||
} | ||
export function getEndOfPreviousMonth(date, offset = 1) { | ||
const previousMonth = getDifferentMonth(date, -offset); | ||
return getEndOfMonth(previousMonth); | ||
} | ||
export function getBeginOfNextMonth(date, offset = 1) { | ||
const nextMonth = getDifferentMonth(date, offset); | ||
return getBeginOfMonth(nextMonth); | ||
} | ||
export function getBeginOfDay(date) { | ||
const year = getYear(date); | ||
const monthIndex = getMonthIndex(date); | ||
const day = getDay(date); | ||
return new Date(year, monthIndex, day); | ||
} | ||
export function getEndOfDay(date) { | ||
const year = getYear(date); | ||
const monthIndex = getMonthIndex(date); | ||
const day = getDay(date); | ||
return new Date(year, monthIndex, day + 1, 0, 0, 0, -1); | ||
} | ||
/** | ||
* Returns an array with the beginning and the end of a given day. | ||
* | ||
* @param {Date} date Date. | ||
*/ | ||
export function getDayRange(date) { | ||
return [ | ||
getBeginOfDay(date), | ||
getEndOfDay(date), | ||
]; | ||
} | ||
/** | ||
* Gets week number according to ISO 8601 or US standard. | ||
@@ -277,4 +109,8 @@ * In ISO 8601, Arabic and Hebrew week 1 is the one with January 4. | ||
*/ | ||
export function getWeekNumber(date, calendarType = 'ISO 8601') { | ||
const calendarTypeForWeekNumber = calendarType === 'US' ? 'US' : 'ISO 8601'; | ||
export function getWeekNumber(date, calendarType = CALENDAR_TYPES.ISO_8601) { | ||
const calendarTypeForWeekNumber = ( | ||
calendarType === CALENDAR_TYPES.US | ||
? CALENDAR_TYPES.US | ||
: CALENDAR_TYPES.ISO_8601 | ||
); | ||
const beginOfWeek = getBeginOfWeek(date, calendarTypeForWeekNumber); | ||
@@ -287,3 +123,3 @@ let year = getYear(date) + 1; | ||
do { | ||
dayInWeekOne = new Date(year, 0, calendarTypeForWeekNumber === 'ISO 8601' ? 4 : 1); | ||
dayInWeekOne = new Date(year, 0, calendarTypeForWeekNumber === CALENDAR_TYPES.ISO_8601 ? 4 : 1); | ||
beginOfFirstWeek = getBeginOfWeek(dayInWeekOne, calendarTypeForWeekNumber); | ||
@@ -297,2 +133,6 @@ year -= 1; | ||
/** | ||
* Others | ||
*/ | ||
/** | ||
* Returns the beginning of a given range. | ||
@@ -305,14 +145,8 @@ * | ||
switch (rangeType) { | ||
case 'century': | ||
return getBeginOfCentury(date); | ||
case 'decade': | ||
return getBeginOfDecade(date); | ||
case 'year': | ||
return getBeginOfYear(date); | ||
case 'month': | ||
return getBeginOfMonth(date); | ||
case 'day': | ||
return getBeginOfDay(date); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'century': return getCenturyStart(date); | ||
case 'decade': return getDecadeStart(date); | ||
case 'year': return getYearStart(date); | ||
case 'month': return getMonthStart(date); | ||
case 'day': return getDayStart(date); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -323,12 +157,7 @@ } | ||
switch (rangeType) { | ||
case 'century': | ||
return getBeginOfPreviousCentury(date); | ||
case 'decade': | ||
return getBeginOfPreviousDecade(date); | ||
case 'year': | ||
return getBeginOfPreviousYear(date); | ||
case 'month': | ||
return getBeginOfPreviousMonth(date); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'century': return getPreviousCenturyStart(date); | ||
case 'decade': return getPreviousDecadeStart(date); | ||
case 'year': return getPreviousYearStart(date); | ||
case 'month': return getPreviousMonthStart(date); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -339,12 +168,7 @@ } | ||
switch (rangeType) { | ||
case 'century': | ||
return getBeginOfNextCentury(date); | ||
case 'decade': | ||
return getBeginOfNextDecade(date); | ||
case 'year': | ||
return getBeginOfNextYear(date); | ||
case 'month': | ||
return getBeginOfNextMonth(date); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'century': return getNextCenturyStart(date); | ||
case 'decade': return getNextDecadeStart(date); | ||
case 'year': return getNextYearStart(date); | ||
case 'month': return getNextMonthStart(date); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -355,10 +179,6 @@ } | ||
switch (rangeType) { | ||
case 'decade': | ||
return getBeginOfPreviousDecade(date, 100); | ||
case 'year': | ||
return getBeginOfPreviousYear(date, 10); | ||
case 'month': | ||
return getBeginOfPreviousMonth(date, 12); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'decade': return getPreviousDecadeStart(date, -100); | ||
case 'year': return getPreviousYearStart(date, -10); | ||
case 'month': return getPreviousMonthStart(date, -12); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -369,10 +189,6 @@ }; | ||
switch (rangeType) { | ||
case 'decade': | ||
return getBeginOfNextDecade(date, 100); | ||
case 'year': | ||
return getBeginOfNextYear(date, 10); | ||
case 'month': | ||
return getBeginOfNextMonth(date, 12); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'decade': return getNextDecadeStart(date, 100); | ||
case 'year': return getNextYearStart(date, 10); | ||
case 'month': return getNextMonthStart(date, 12); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -389,14 +205,8 @@ }; | ||
switch (rangeType) { | ||
case 'century': | ||
return getEndOfCentury(date); | ||
case 'decade': | ||
return getEndOfDecade(date); | ||
case 'year': | ||
return getEndOfYear(date); | ||
case 'month': | ||
return getEndOfMonth(date); | ||
case 'day': | ||
return getEndOfDay(date); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'century': return getCenturyEnd(date); | ||
case 'decade': return getDecadeEnd(date); | ||
case 'year': return getYearEnd(date); | ||
case 'month': return getMonthEnd(date); | ||
case 'day': return getDayEnd(date); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -407,12 +217,7 @@ } | ||
switch (rangeType) { | ||
case 'century': | ||
return getEndOfPreviousCentury(date); | ||
case 'decade': | ||
return getEndOfPreviousDecade(date); | ||
case 'year': | ||
return getEndOfPreviousYear(date); | ||
case 'month': | ||
return getEndOfPreviousMonth(date); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'century': return getPreviousCenturyEnd(date); | ||
case 'decade': return getPreviousDecadeEnd(date); | ||
case 'year': return getPreviousYearEnd(date); | ||
case 'month': return getPreviousMonthEnd(date); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -423,10 +228,6 @@ } | ||
switch (rangeType) { | ||
case 'decade': | ||
return getEndOfPreviousDecade(date, 100); | ||
case 'year': | ||
return getEndOfPreviousYear(date, 10); | ||
case 'month': | ||
return getEndOfPreviousMonth(date, 12); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'decade': return getPreviousDecadeEnd(date, -100); | ||
case 'year': return getPreviousYearEnd(date, -10); | ||
case 'month': return getPreviousMonthEnd(date, -12); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -443,14 +244,8 @@ }; | ||
switch (rangeType) { | ||
case 'century': | ||
return getCenturyRange(date); | ||
case 'decade': | ||
return getDecadeRange(date); | ||
case 'year': | ||
return getYearRange(date); | ||
case 'month': | ||
return getMonthRange(date); | ||
case 'day': | ||
return getDayRange(date); | ||
default: | ||
throw new Error(`Invalid rangeType: ${rangeType}`); | ||
case 'century': return getCenturyRange(date); | ||
case 'decade': return getDecadeRange(date); | ||
case 'year': return getYearRange(date); | ||
case 'month': return getMonthRange(date); | ||
case 'day': return getDayRange(date); | ||
default: throw new Error(`Invalid rangeType: ${rangeType}`); | ||
} | ||
@@ -474,17 +269,8 @@ } | ||
/** | ||
* Returns a number of days in a month of a given date. | ||
* | ||
* @param {Date} date Date. | ||
*/ | ||
export function getDaysInMonth(date) { | ||
const year = getYear(date); | ||
const monthIndex = getMonthIndex(date); | ||
return new Date(year, monthIndex + 1, 0).getDate(); | ||
function toYearLabel(locale, formatYear = defaultFormatYear, dates) { | ||
return dates | ||
.map(date => formatYear(locale, date)) | ||
.join(' – '); | ||
} | ||
function toYearLabel([start, end]) { | ||
return `${getYear(start)} – ${getYear(end)}`; | ||
} | ||
/** | ||
@@ -496,4 +282,4 @@ * Returns a string labelling a century of a given date. | ||
*/ | ||
export function getCenturyLabel(date) { | ||
return toYearLabel(getCenturyRange(date)); | ||
export function getCenturyLabel(locale, formatYear, date) { | ||
return toYearLabel(locale, formatYear, getCenturyRange(date)); | ||
} | ||
@@ -507,4 +293,4 @@ | ||
*/ | ||
export function getDecadeLabel(date) { | ||
return toYearLabel(getDecadeRange(date)); | ||
export function getDecadeLabel(locale, formatYear, date) { | ||
return toYearLabel(locale, formatYear, getDecadeRange(date)); | ||
} | ||
@@ -517,10 +303,10 @@ | ||
*/ | ||
export function isWeekend(date, calendarType = 'ISO 8601') { | ||
export function isWeekend(date, calendarType = CALENDAR_TYPES.ISO_8601) { | ||
const weekday = date.getDay(); | ||
switch (calendarType) { | ||
case 'Arabic': | ||
case 'Hebrew': | ||
case CALENDAR_TYPES.ARABIC: | ||
case CALENDAR_TYPES.HEBREW: | ||
return weekday === FRIDAY || weekday === SATURDAY; | ||
case 'ISO 8601': | ||
case 'US': | ||
case CALENDAR_TYPES.ISO_8601: | ||
case CALENDAR_TYPES.US: | ||
return weekday === SATURDAY || weekday === SUNDAY; | ||
@@ -531,42 +317,1 @@ default: | ||
} | ||
/** | ||
* Returns local month in ISO-like format (YYYY-MM). | ||
*/ | ||
export function getISOLocalMonth(value) { | ||
if (!value) { | ||
return value; | ||
} | ||
const date = new Date(value); | ||
if (isNaN(date.getTime())) { | ||
throw new Error(`Invalid date: ${value}`); | ||
} | ||
const year = getYear(date); | ||
const month = `0${getMonth(date)}`.slice(-2); | ||
return `${year}-${month}`; | ||
} | ||
/** | ||
* Returns local date in ISO-like format (YYYY-MM-DD). | ||
*/ | ||
export function getISOLocalDate(value) { | ||
if (!value) { | ||
return value; | ||
} | ||
const date = new Date(value); | ||
if (isNaN(date.getTime())) { | ||
throw new Error(`Invalid date: ${value}`); | ||
} | ||
const year = getYear(date); | ||
const month = `0${getMonth(date)}`.slice(-2); | ||
const day = `0${getDay(date)}`.slice(-2); | ||
return `${year}-${month}-${day}`; | ||
} |
import PropTypes from 'prop-types'; | ||
const calendarTypes = ['ISO 8601', 'US', 'Arabic', 'Hebrew']; | ||
import { CALENDAR_TYPES } from './const'; | ||
const calendarTypes = Object.values(CALENDAR_TYPES); | ||
const allViews = ['century', 'decade', 'year', 'month']; | ||
@@ -5,0 +7,0 @@ |
@@ -11,3 +11,3 @@ import React from 'react'; | ||
className, | ||
count, | ||
count = 3, | ||
dateTransform, | ||
@@ -19,3 +19,3 @@ dateType, | ||
start, | ||
step, | ||
step = 1, | ||
tile: Tile, | ||
@@ -64,6 +64,1 @@ value, | ||
}; | ||
TileGroup.defaultProps = { | ||
count: 3, | ||
step: 1, | ||
}; |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { getMonthStart, getMonthEnd } from '@wojtekmaj/date-utils'; | ||
@@ -7,6 +8,2 @@ import Tile from '../Tile'; | ||
import { | ||
getBeginOfMonth, | ||
getEndOfMonth, | ||
} from '../shared/dates'; | ||
import { | ||
formatMonth as defaultFormatMonth, | ||
@@ -22,3 +19,3 @@ formatMonthYear, | ||
date, | ||
formatMonth, | ||
formatMonth = defaultFormatMonth, | ||
locale, | ||
@@ -34,4 +31,4 @@ ...otherProps | ||
locale={locale} | ||
maxDateTransform={getEndOfMonth} | ||
minDateTransform={getBeginOfMonth} | ||
maxDateTransform={getMonthEnd} | ||
minDateTransform={getMonthStart} | ||
view="year" | ||
@@ -44,6 +41,2 @@ > | ||
Month.defaultProps = { | ||
formatMonth: defaultFormatMonth, | ||
}; | ||
Month.propTypes = { | ||
@@ -50,0 +43,0 @@ ...tileProps, |
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { getYear } from '@wojtekmaj/date-utils'; | ||
@@ -7,3 +8,2 @@ import TileGroup from '../TileGroup'; | ||
import { getYear } from '../shared/dates'; | ||
import { tileGroupProps } from '../shared/propTypes'; | ||
@@ -10,0 +10,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
424236
105
9847
206
2
1
+ Added@wojtekmaj/date-utils@^1.0.0
+ Added@wojtekmaj/date-utils@1.5.1(transitive)
- Removedreact-lifecycles-compat@^3.0.4
- Removedreact-lifecycles-compat@3.0.4(transitive)