palantir / blueprint

A React-based UI toolkit for the web
https://blueprintjs.com/
Apache License 2.0
20.67k stars 2.17k forks source link

Date range picker: range selection to day not intuitive (not consistent with react-day-picker) #3890

Open Redirts opened 4 years ago

Redirts commented 4 years ago

Environment

Actual behavior

I have a range selected and I want to just select one specific day (without range). The way this works in Date range picker (BlueprintJS) implementation is not intuitive and also it is not consistent with how it works in react-day-picker.

Blueprint Date range picker: Video made directly from https://blueprintjs.com/docs/#datetime/daterangepicker

2019-12-11_12-47-58

Expected behavior

React-day-picker: Video made directly from http://react-day-picker.js.org/examples/selected-range/

2019-12-11_12-48-44

This method makes much more sense to me. If I have a range selected and click on either the start/end range day, then the range should be stopped and the individual day should be picked.

Possible solution

adidahiya commented 4 years ago

It looks like you did not enable the "Allow single day range" option, can you try that?

Redirts commented 4 years ago

No, it still does not behave as expected. See the video below:

2020-01-07_10-24-09

LoiKos commented 2 years ago

Hi, I fall into this problem. I don't try it out but In this method :

https://github.com/palantir/blueprint/blob/6f6310d1e226cd46a6b02fc959c62c530aff5c82/packages/datetime/src/dateRangeSelectionStrategy.ts#L118

I think there is a missing piece in the case of allowSingleDayRange to allow to start a range from a single day range:

private static getDefaultNextState(
        selectedRange: DateRange,
        day: Date,
        allowSingleDayRange: boolean,
    ): IDateRangeSelectionState {
        const [start, end] = selectedRange;

        let nextDateRange: DateRange;

        if (start == null && end == null) {
            nextDateRange = [day, null];
        } else if (start != null && end == null) {
            nextDateRange = this.createRange(day, start, allowSingleDayRange);
        } else if (start == null && end != null) {
            nextDateRange = this.createRange(day, end, allowSingleDayRange);
        } else {
            const isStart = areSameDay(start, day);
            const isEnd = areSameDay(end, day);
            if (isStart && isEnd) {
                nextDateRange = [null, null];
            } else if (isStart) {
                nextDateRange = [null, end];
            } else if (isEnd) {
                nextDateRange = [start, null];
            } else {
                if(allowSingleDayRange && areSameDay(start, end)){
                nextDateRange  = this.createRange(day, start, allowSingleDayRange);
                } else {
                nextDateRange = [day, null];
                }
            }
        }

        return { dateRange: nextDateRange };
    }