Skip to content

Commit

Permalink
feat: added minDate/maxDate to DatePicker
Browse files Browse the repository at this point in the history
  • Loading branch information
schummar committed Sep 13, 2023
1 parent adb02f8 commit dfd3b0d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
2 changes: 1 addition & 1 deletion docs/stories/_default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const _defaultColumns: TableProps<Person>['columns'] = (col) => [
col((x) => x.birthday, {
header: 'Birthday',
renderCell: (birthday) => dateFormat.format(new Date(birthday)),
filter: <DateFilter />,
filter: <DateFilter maxDate={new Date()} />,
}),
];

Expand Down
9 changes: 8 additions & 1 deletion src/components/dateFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ export function DateFilter<T, V>({
quickOptions,
singleSelect,
filterBy = convertDateOrArray,
minDate,
maxDate,
...props
}: {
/** If enabled, only single days can be selected. Ranges otherwise. */
singleSelect?: boolean;
} & Pick<DatePickerProps, 'locale' | 'firstDayOfWeek' | 'defaultDateInView' | 'quickOptions'> &
} & Pick<
DatePickerProps,
'locale' | 'firstDayOfWeek' | 'defaultDateInView' | 'quickOptions' | 'minDate' | 'maxDate'
> &
CommonFilterProps<T, V, Date | DateRange | null, Date | DateRange | null>): JSX.Element {
const { value = null, onChange } = useFilter({
...props,
Expand Down Expand Up @@ -68,6 +73,8 @@ export function DateFilter<T, V>({
firstDayOfWeek={firstDayOfWeek}
defaultDateInView={defaultDateInView}
quickOptions={quickOptions}
minDate={minDate}
maxDate={maxDate}
/>
</div>
);
Expand Down
35 changes: 34 additions & 1 deletion src/components/datePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export type DatePickerProps = {
defaultDateInView?: Date;
/** Show buttons to quickly select suggested dates or date ranges */
quickOptions?: DatePickerQuickOption[];
minDate?: Date;
maxDate?: Date;
};

const weekDays = [0, 1, 2, 3, 4, 5, 6] as const;
Expand Down Expand Up @@ -138,17 +140,43 @@ 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 dateClamp(date: Date, min?: Date, max?: Date) {
if (min && date < min) {
return min;
}

if (max && date > max) {
return max;
}

return date;
}

export function DatePicker(props: DatePickerProps) {
const {
value,
onChange,
rangeSelect,
locale,
firstDayOfWeek = 1,
defaultDateInView,
quickOptions = ['today', 'thisWeek'],
minDate,
maxDate,
} = props;

function onChange(value: Date | DateRange | null) {
if (value instanceof Date) {
value = dateClamp(value, minDate, maxDate);
} else if (value) {
value = {
min: dateClamp(value.min, minDate, maxDate),
max: dateClamp(value.max, minDate, maxDate),
};
}

props.onChange(value);
}

const Button = useTheme((t) => t.components.Button);
const IconButton = useTheme((t) => t.components.IconButton);
const ChevronRight = useTheme((t) => t.icons.ChevronRight);
Expand Down Expand Up @@ -201,6 +229,8 @@ export function DatePicker(props: DatePickerProps) {
onOffsetChanged: (offset) =>
setDateInView(new Date(dateInView.getFullYear(), dateInView.getMonth() + offset)),
offset: 0,
minDate,
maxDate,
});
const now = useMemo(() => startOfDay(new Date()), []);

Expand Down Expand Up @@ -333,12 +363,14 @@ export function DatePicker(props: DatePickerProps) {

const { prevMonth, nextMonth, date } = dateObject;
const today = startOfDay(date).getTime() === now.getTime();
const disabled = (minDate && date < minDate) || (maxDate && date > maxDate);

const selected =
date.getTime() === min?.getTime() ||
(min && max && dateIntersect(date, { min, max }));
const preSelected =
!selected &&
!disabled &&
(date.getTime() === hovered?.getTime() ||
(min &&
!max &&
Expand Down Expand Up @@ -384,6 +416,7 @@ export function DatePicker(props: DatePickerProps) {
}}
onPointerOver={() => setHovered(date)}
onPointerOut={() => setHovered(undefined)}
disabled={disabled}
>
{date.getDate()}
</button>
Expand Down

0 comments on commit dfd3b0d

Please sign in to comment.