Skip to content

Commit

Permalink
feat: more DatePicker options
Browse files Browse the repository at this point in the history
  • Loading branch information
schummar committed Sep 6, 2022
1 parent a9f4744 commit 20d7ff6
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 41 deletions.
20 changes: 13 additions & 7 deletions src/components/dateFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import { useFilter } from '..';
import { CommonFilterProps } from '../types';
import { dateIntersect, DatePicker, DatePickerProps, DateRange } from './datePicker';
Expand Down Expand Up @@ -28,17 +27,16 @@ function convertDateOrArray(x: unknown): Date | DateRange | (Date | DateRange)[]
export function DateFilter<T, V>({
locale,
firstDayOfWeek,
defaultDateInView,
quickOptions,
singleSelect,
filterBy = convertDateOrArray,
...props
}: {
/** Which locale to use to render the calendar. */
locale?: string;
/** Which day of the week should be in the first column. */
firstDayOfWeek?: DatePickerProps['firstDayOfWeek'];
/** If enabled, only single days can be selected. Ranges otherwise. */
singleSelect?: boolean;
} & CommonFilterProps<T, V, Date | DateRange | null, Date | DateRange | null>): JSX.Element {
} & Pick<DatePickerProps, 'locale' | 'firstDayOfWeek' | 'defaultDateInView' | 'quickOptions'> &
CommonFilterProps<T, V, Date | DateRange | null, Date | DateRange | null>): JSX.Element {
const { value = null, onChange } = useFilter({
...props,
filterBy,
Expand All @@ -61,7 +59,15 @@ export function DateFilter<T, V>({
display: 'grid',
}}
>
<DatePicker rangeSelect={!singleSelect} value={value} onChange={onChange} locale={locale} firstDayOfWeek={firstDayOfWeek} />
<DatePicker
rangeSelect={!singleSelect}
value={value}
onChange={onChange}
locale={locale}
firstDayOfWeek={firstDayOfWeek}
defaultDateInView={defaultDateInView}
quickOptions={quickOptions}
/>
</div>
);
}
78 changes: 44 additions & 34 deletions src/components/datePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useDayzed } from 'dayzed';
import React, { useEffect, useMemo, useState } from 'react';
import { ReactNode, useEffect, useMemo, useState } from 'react';
import { useTheme } from '..';
import { gray } from '../theme/defaultTheme/defaultClasses';
import { useCssVariables } from '../theme/useCssVariables';
import { DateInput } from './dateInput';

export type DateRange = { min: Date; max: Date };

export type DatePickerQuickOption = { label: ReactNode; value: Date | DateRange | (() => Date | DateRange) };

export type DatePickerProps = {
/** Currently selected day or range of days. */
value: Date | DateRange | null;
Expand All @@ -18,6 +20,10 @@ export type DatePickerProps = {
locale?: string;
/** Which day of the week should be in the first column. */
firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
/** Which month to show initially */
defaultDateInView?: Date;
/** Show buttons to quickly select suggested dates or date ranges */
quickOptions?: DatePickerQuickOption[] | ((onChange: (value: Date | DateRange | null) => void) => ReactNode);
};

const weekDays = [0, 1, 2, 3, 4, 5, 6] as const;
Expand Down Expand Up @@ -65,7 +71,15 @@ export function dateIntersect(a: Date | null | DateRange, b: Date | null | DateR
return !(endOfDay(a.max) < startOfDay(b.min) || startOfDay(a.min) > endOfDay(b.max));
}

export function DatePicker({ value, onChange, rangeSelect, locale, firstDayOfWeek = 0 }: DatePickerProps) {
export function DatePicker({
value,
onChange,
rangeSelect,
locale,
firstDayOfWeek = 0,
defaultDateInView = new Date(),
quickOptions,
}: DatePickerProps) {
const Button = useTheme((t) => t.components.Button);
const IconButton = useTheme((t) => t.components.IconButton);
const ChevronRight = useTheme((t) => t.icons.ChevronRight);
Expand All @@ -74,14 +88,18 @@ export function DatePicker({ value, onChange, rangeSelect, locale, firstDayOfWee
const textReset = useTheme((t) => t.text.reset);
const cssVariables = useCssVariables();

const [baseDate] = useState(new Date());
const [dateInView, setDateInView] = useState<Date>(baseDate);
const [dateInView, setDateInView] = useState<Date>(defaultDateInView);
const [dirty, setDirty] = useState<Partial<DateRange>>();
const [hovered, setHovered] = useState<Date>();

const min = dirty ? dirty.min : value instanceof Date ? value : value?.min;
const max = dirty ? dirty.max : value instanceof Date ? value : value?.max;

quickOptions ??= [
{ label: textToday, value: today },
{ label: textThisWeek, value: thisWeek },
];

const { calendars, getBackProps, getForwardProps, getDateProps } = useDayzed({
onDateSelected: () => undefined,
firstDayOfWeek,
Expand All @@ -96,7 +114,7 @@ export function DatePicker({ value, onChange, rangeSelect, locale, firstDayOfWee
return (weekDay: number) => format(new Date(Date.UTC(2021, 5, weekDay)));
}, [locale]);

useEffect(() => setDateInView(value === null ? new Date() : value instanceof Date ? value : value.max), [value]);
useEffect(() => setDateInView(value === null ? defaultDateInView : value instanceof Date ? value : value.max), [value]);

useEffect(() => {
if (!rangeSelect) {
Expand Down Expand Up @@ -250,35 +268,27 @@ export function DatePicker({ value, onChange, rangeSelect, locale, firstDayOfWee
))}

<div css={{ marginTop: 'var(--spacing)', display: 'grid', gridAutoFlow: 'column', justifyContent: 'center' }}>
<Button
variant="text"
onClick={() => {
setDirty(undefined);
onChange(today());
}}
>
{textToday}
</Button>

<Button
variant="text"
onClick={() => {
setDirty(undefined);
onChange(thisWeek(firstDayOfWeek));
}}
>
{textThisWeek}
</Button>

<Button
variant="text"
onClick={() => {
setDirty(undefined);
onChange(null);
}}
>
{textReset}
</Button>
{quickOptions instanceof Function
? quickOptions((value) => {
setDirty(undefined);
onChange(value);
})
: [...quickOptions, { label: textReset, value: null }].map(({ label, value }, index) => (
<Button
key={index}
variant="text"
onClick={() => {
if (value instanceof Function) {
value = value();
}

setDirty(undefined);
onChange(value);
}}
>
{label}
</Button>
))}
</div>
</div>
);
Expand Down

0 comments on commit 20d7ff6

Please sign in to comment.