Skip to content

Commit

Permalink
feat: added DateRangePicker (#91)
Browse files Browse the repository at this point in the history
* feat: added DateRangePicker

* feat: accept string as date value in range calendar picker

* chore: review changes

* fix: date range picker segment isDisabled/ReadOnly

* fix: dateRangePicker min/max invalid

* fix: calendar state / range calendar state default values

* chore: review updates
  • Loading branch information
anuraghazra authored Oct 14, 2020
1 parent 67de3d5 commit 0a1cabd
Show file tree
Hide file tree
Showing 10 changed files with 492 additions and 118 deletions.
2 changes: 1 addition & 1 deletion src/calendar/__utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ export function makeRange(start: Date, end: Date): RangeValue<Date> {
[start, end] = [end, start];
}

return { start: start, end: endOfDay(end) };
return { start, end };
}
63 changes: 11 additions & 52 deletions src/calendar/stories/CalendarComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import React from "react";

import "./index.css";
import {
ChevronLeft,
ChevronRight,
DoubleChevronLeft,
DoubleChevronRight,
} from "./svg-icons";

import {
Calendar as CalendarWrapper,
CalendarButton,
Expand All @@ -19,65 +26,17 @@ export const CalendarComp: React.FC<CalendarStateReturn> = state => {
<CalendarWrapper {...state} className="calendar">
<div className="header">
<CalendarButton {...state} goto="previousYear" className="prev-year">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M11 19l-7-7 7-7m8 14l-7-7 7-7"
></path>
</svg>
<DoubleChevronLeft />
</CalendarButton>
<CalendarButton {...state} goto="previousMonth" className="prev-month">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M15 19l-7-7 7-7"
></path>
</svg>
<ChevronLeft />
</CalendarButton>
<CalendarHeader {...state} />
<CalendarButton {...state} goto="nextMonth" className="next-month">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 5l7 7-7 7"
></path>
</svg>
<ChevronRight />
</CalendarButton>
<CalendarButton {...state} goto="nextYear" className="next-year">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 5l7 7-7 7M5 5l7 7-7 7"
></path>
</svg>
<DoubleChevronRight />
</CalendarButton>
</div>

Expand Down
69 changes: 14 additions & 55 deletions src/calendar/stories/RangeCalendar.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import * as React from "react";
import { Meta } from "@storybook/react";
import { addDays, addWeeks, format, subDays } from "date-fns";
import { addDays, addWeeks, subDays, format } from "date-fns";
import "./range-style.css";

import {
ChevronLeft,
ChevronRight,
DoubleChevronLeft,
DoubleChevronRight,
} from "./svg-icons";

import {
Calendar,
Expand All @@ -11,10 +19,9 @@ import {
CalendarCellButton,
CalendarWeekTitle,
} from "../index";
import "./range-style.css";
import {
RangeCalendarInitialState,
useRangeCalendarState,
RangeCalendarInitialState,
} from "../RangeCalendarState";

export default {
Expand All @@ -32,65 +39,17 @@ const RangeCalendarComp: React.FC<RangeCalendarInitialState> = props => {
>
<div className="header">
<CalendarButton {...state} goto="previousYear" className="prev-year">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M11 19l-7-7 7-7m8 14l-7-7 7-7"
></path>
</svg>
<DoubleChevronLeft />
</CalendarButton>
<CalendarButton {...state} goto="previousMonth" className="prev-month">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M15 19l-7-7 7-7"
></path>
</svg>
<ChevronLeft />
</CalendarButton>
<CalendarHeader {...state} />
<CalendarButton {...state} goto="nextMonth" className="next-month">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 5l7 7-7 7"
></path>
</svg>
<ChevronRight />
</CalendarButton>
<CalendarButton {...state} goto="nextYear" className="next-year">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 5l7 7-7 7M5 5l7 7-7 7"
></path>
</svg>
<DoubleChevronRight />
</CalendarButton>
</div>

Expand Down
47 changes: 47 additions & 0 deletions src/calendar/stories/svg-icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from "react";

export const DoubleChevronLeft = ({ ...props }) => {
return (
<svg
{...props}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M15 19l-7-7 7-7"
></path>
</svg>
);
};

export const ChevronLeft = ({ ...props }) => {
return (
<svg
{...props}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M11 19l-7-7 7-7m8 14l-7-7 7-7"
></path>
</svg>
);
};

export const ChevronRight = () => {
return <ChevronLeft style={{ transform: "rotate(180deg)" }} />;
};

export const DoubleChevronRight = () => {
return <DoubleChevronLeft style={{ transform: "rotate(180deg)" }} />;
};
8 changes: 6 additions & 2 deletions src/datepicker/DatePickerSegment.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { DatePickerStateReturn } from ".";
import { createComponent, createHook } from "reakit-system";

import { useSegment, SegmentOptions, SegmentHTMLProps } from "../segment";
import { DATE_PICKER_SEGMENT_KEYS } from "./__keys";
import { DateRangePickerStateReturn } from "./DateRangePickerState";
import { useSegment, SegmentOptions, SegmentHTMLProps } from "../segment";

export type DatePickerSegmentOptions = SegmentOptions & DatePickerStateReturn;
export type DatePickerSegmentOptions =
| SegmentOptions
| Partial<DatePickerStateReturn>
| Partial<DateRangePickerStateReturn>;

export type DatePickerSegmentHTMLProps = SegmentHTMLProps;

Expand Down
11 changes: 7 additions & 4 deletions src/datepicker/DatePickerSegmentField.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { createComponent, createHook } from "reakit-system";

import {
SegmentFieldHTMLProps,
SegmentFieldOptions,
useSegmentField,
SegmentFieldOptions,
SegmentFieldHTMLProps,
} from "../segment";
import { DATE_PICKER_SEGMENT_FIELD_KEYS } from "./__keys";
import { DatePickerStateReturn } from "./DatePickerState";
import { DateRangePickerStateReturn } from "./DateRangePickerState";

export type DatePickerSegmentFieldOptions = SegmentFieldOptions &
DatePickerStateReturn;
export type DatePickerSegmentFieldOptions =
| SegmentFieldOptions
| Partial<DatePickerStateReturn>
| Partial<DateRangePickerStateReturn>;

export type DatePickerSegmentFieldHTMLProps = SegmentFieldHTMLProps;

Expand Down
10 changes: 7 additions & 3 deletions src/datepicker/DatePickerState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export interface DatePickerInitialState
FocusableProps,
ValueBase<string>,
RangeValueBase<string> {
placeholderDate?: string;
formatOptions?: DateTimeFormatOpts;
placeholderDate?: Date;
}

export const useDatePickerState = (props: DatePickerInitialState = {}) => {
Expand All @@ -39,7 +39,7 @@ export const useDatePickerState = (props: DatePickerInitialState = {}) => {
isRequired,
autoFocus,
formatOptions,
placeholderDate,
placeholderDate: placeholderDateProp,
} = props;

const onChange = React.useCallback(
Expand All @@ -51,13 +51,15 @@ export const useDatePickerState = (props: DatePickerInitialState = {}) => {

const [value, setValue] = useControllableState({
value: parseDate(initialDate),
defaultValue: parseDate(defaultValueProp) || new Date(),
defaultValue:
parseDate(defaultValueProp) || parseDate(stringifyDate(new Date())),
onChange,
shouldUpdate: (prev, next) => prev !== next,
});

const minValue = parseDate(minValueProp);
const maxValue = parseDate(maxValueProp);
const placeholderDate = parseDate(placeholderDateProp);

const selectDate = (newValue: string) => {
const newDate = parseDate(newValue);
Expand All @@ -75,6 +77,8 @@ export const useDatePickerState = (props: DatePickerInitialState = {}) => {
const calendar = useCalendarState({
value: stringifyDate(value),
onChange: selectDate,
minValue: minValueProp,
maxValue: maxValueProp,
});

const validationState: ValidationState =
Expand Down
Loading

0 comments on commit 0a1cabd

Please sign in to comment.