diff --git a/CHANGELOG.md b/CHANGELOG.md index c5326d0..c20706b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.0] - 2021-11-03 +### Added +- Added nullable property to `Calendar`, `DatePicker`, `DateRangePicker`, and `WeekPicker` that allow set value to null. Property nullable is as a default set to false. + ## [0.5.1] - 2021-11-03 ### Fixed - Fixed `MonthPicker` to correctly forward the value to `MonthInput`. diff --git a/package.json b/package.json index 32e9aee..a8d8613 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "daycy", - "version": "0.5.1", + "version": "0.6.0", "description": "Simple date (range) picker for React based on Semantic-UI.", "main": "./dist/index.js", "scripts": { diff --git a/src/Calendar.js b/src/Calendar.js index c05bc3e..93b0035 100644 --- a/src/Calendar.js +++ b/src/Calendar.js @@ -27,14 +27,16 @@ export default class Calendar extends Component { includeWeeks: PropTypes.bool, onWeekSelect: PropTypes.func, translate: PropTypes.func, + nullable: PropTypes.bool, }; static defaultProps = { includeWeeks: false, onClose: () => {}, + nullable: false, }; - state = { month: null, weeks: null, hoverWeek: null, hoverDate: null }; + state = { month: null, weeks: null, hoverWeek: null, hoverDate: null, hoverClear: false }; constructor(...args) { super(...args); @@ -54,7 +56,7 @@ export default class Calendar extends Component { { month, weeks, hoverDate }, ) { const updates = {}; - + if (value) { updates.value = value.startOf('day'); } else { @@ -74,7 +76,7 @@ export default class Calendar extends Component { const date = ( value || highlightStart || - highlightEnd || + highlightEnd || DateTime.local() ); month = date.startOf('month'); @@ -122,7 +124,7 @@ export default class Calendar extends Component { onChange(date) { const { value, onChange } = this.props - if (value) { + if (value && date !== null) { date = date.set({ hour: value.hour, minute: value.minute, @@ -195,7 +197,7 @@ export default class Calendar extends Component { ( hover === 'start' && highlightEnd && - date >= hoverDate && + date >= hoverDate && date <= highlightEnd ) || ( @@ -227,16 +229,16 @@ export default class Calendar extends Component { } render() { - const { includeWeeks, open, trigger, onClose } = this.props; - const { month, weeks } = this.state; + const { includeWeeks, open, trigger, onClose, nullable } = this.props; + const { month, weeks, hoverClear } = this.state; return ( - e.preventDefault()} > @@ -259,6 +261,18 @@ export default class Calendar extends Component { {DAYS.map(this.renderDay)} {weeks && weeks.map(this.renderWeek)} +
+ {nullable && ( +
this.onChange(null)} + onMouseEnter={() => this.setState({hoverClear: true})} + onMouseLeave={() => this.setState({hoverClear: false})} + > + {this.translate('clear.label')} +
+ )} +
); diff --git a/src/DatePicker.js b/src/DatePicker.js index a14ad51..d7f09e1 100644 --- a/src/DatePicker.js +++ b/src/DatePicker.js @@ -15,12 +15,14 @@ export default class DatePicker extends Component { includeWeeks: PropTypes.bool, onWeekSelect: PropTypes.func, noPopup: PropTypes.bool, + nullable: PropTypes.bool, }; static defaultProps = { format: 'dd-LL-yyyy', fluid: false, noPopup: false, + nullable: false, }; state = { open: false }; @@ -60,7 +62,7 @@ export default class DatePicker extends Component { } render() { - const { value, translate, includeWeeks, onWeekSelect, noPopup, ...props } = this.props; + const { value, translate, includeWeeks, onWeekSelect, nullable, noPopup, ...props } = this.props; const { open } = this.state; delete props.onChange; @@ -71,6 +73,7 @@ export default class DatePicker extends Component { open={!noPopup && open} value={value} onChange={this.onChange} + nullable={nullable} trigger={ this.input = ref} diff --git a/src/DateRangePicker.js b/src/DateRangePicker.js index 2c0de25..1a9e140 100644 --- a/src/DateRangePicker.js +++ b/src/DateRangePicker.js @@ -27,6 +27,7 @@ export default class DateRangePicker extends Component { includeWeeks: PropTypes.bool, disabled: PropTypes.bool, noPopup: PropTypes.bool, + nullable: PropTypes.bool, }; static defaultProps = { @@ -39,6 +40,7 @@ export default class DateRangePicker extends Component { fluid: false, disabled: false, noPopup: false, + nullable: false, }; state = { open: null, override: null }; @@ -58,11 +60,14 @@ export default class DateRangePicker extends Component { onChange(date, close = true) { let { value, onChange } = this.props; const { open, override } = this.state; + console.log(value, open, override) value = override || value || EMPTY; let other = OTHER[open]; - - if ( + if (date === null){ + onChange(null); + } + else if ( value[other] === null || (open === 'start' && date > value.end) || (open === 'end' && date < value.start) @@ -123,7 +128,7 @@ export default class DateRangePicker extends Component { let { value, format, icon, translate, startProps, endProps, startPlaceholder, endPlaceholder, fluid, includeWeeks, disabled, - noPopup, + noPopup, nullable, ...props } = this.props; const { open, override } = this.state; @@ -156,6 +161,7 @@ export default class DateRangePicker extends Component { value={value[open]} onChange={this.onChange} hover={open} + nullable={nullable} highlightStart={value.start || value.end} highlightEnd={value.end || value.start} trigger={ diff --git a/src/WeekPicker.js b/src/WeekPicker.js index 3b9e968..ff5c911 100644 --- a/src/WeekPicker.js +++ b/src/WeekPicker.js @@ -26,8 +26,8 @@ export function isoWeekEnd({ year, week }) { export default class WeekPicker extends Component { static propTypes = { value: PropTypes.shape({ - year: PropTypes.number.isRequired, - week: PropTypes.number.isRequired, + year: PropTypes.number.isRequired, + week: PropTypes.number.isRequired, }), onChange: PropTypes.func.isRequired, translate: PropTypes.func, @@ -35,6 +35,7 @@ export default class WeekPicker extends Component { format: PropTypes.string, includeDates: PropTypes.bool, noPopup: PropTypes.bool, + nullable: PropTypes.bool, }; static defaultProps = { @@ -42,6 +43,7 @@ export default class WeekPicker extends Component { format: 'dd-LL-yyyy', includeDates: false, noPopup: false, + nullable: false, }; state = { open: false }; @@ -55,10 +57,12 @@ export default class WeekPicker extends Component { onChange(value) { const { onChange } = this.props; - if (value instanceof Interval) { - value = value.start; + if(value !== null) { + if (value instanceof Interval) { + value = value.start; + } + value = {year: value.weekYear, week: value.weekNumber}; } - value = { year: value.weekYear, week: value.weekNumber }; onChange(value); this.onClose(); } @@ -77,7 +81,11 @@ export default class WeekPicker extends Component { } render() { - const { value, includeDates, format, translate, className, fluid, style, noPopup, ...props } = this.props; + const { value, includeDates, format, + translate, className, fluid, + style, noPopup, nullable, + ...props + } = this.props; const { open } = this.state; delete props.onChange; @@ -102,6 +110,7 @@ export default class WeekPicker extends Component { highlightStart={value && isoWeekStart(value)} highlightEnd={value && isoWeekEnd(value)} hover="week" + nullable={nullable} trigger={
.grid > .row.clear { + display: flex; + justify-content: space-around; + flex-flow: row nowrap; + font-weight: bold; + border-bottom: 1px solid rgba(34, 36, 38, 0.15); + padding: 1rem 1rem; + color: rgb(34, 36, 38); +} + +.daycy.calendar > .grid > .row.clear > .cell { + flex: 1 100%; +} + .daycy.calendar > .grid > .row > .cell { display: inline-block; width: 2.3rem; diff --git a/src/translate.js b/src/translate.js index 034f68a..6c909f6 100644 --- a/src/translate.js +++ b/src/translate.js @@ -60,4 +60,7 @@ configureTranslation({ am: 'AM', pm: 'PM', }, + clear: { + label: "Clear", + } }); diff --git a/stories/index.stories.js b/stories/index.stories.js index a7c9d54..55acaf6 100644 --- a/stories/index.stories.js +++ b/stories/index.stories.js @@ -47,6 +47,23 @@ storiesOf('DatePicker', module) style={{ margin: '1rem', width: '19.5rem' }} includeWeeks /> + )) + .add('nullable basic', () => ( + + )) + .add('nullable with weeks', () => ( + )); storiesOf('DateRangePicker', module) @@ -66,6 +83,25 @@ storiesOf('DateRangePicker', module) style={{ margin: '1rem' }} includeWeeks /> + )) + .add('nullable empty', () => ( + + )) + .add('nullable with weeks', () => ( + )); storiesOf('TimePicker', module) @@ -101,6 +137,22 @@ storiesOf('WeekPicker', module) placeholder="Week" style={{ margin: '1rem', width: '19.5rem' }} /> + )) + .add('nullable empty', () => ( + + )) + .add('nullable with dates', () => ( + )); storiesOf('MonthPicker', module) diff --git a/yarn.lock b/yarn.lock index 03e3107..f52779a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2761,9 +2761,9 @@ can-use-dom@^0.1.0: integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo= caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001097: - version "1.0.30001099" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001099.tgz#540118fcc6842d1fde62f4ee5521d1ec6afdb40e" - integrity sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA== + version "1.0.30001279" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001279.tgz" + integrity sha512-VfEHpzHEXj6/CxggTwSFoZBBYGQfQv9Cf42KPlO79sWXCD1QNKWKsKzFeWL7QpZHJQYAvocqV6Rty1yJMkqWLQ== case-sensitive-paths-webpack-plugin@^2.2.0: version "2.3.0"