Skip to content

Commit

Permalink
refactor(date): ♻️ update format & parse to reduce bundle size
Browse files Browse the repository at this point in the history
  • Loading branch information
navin-moorthy committed Sep 7, 2021
1 parent b3707b4 commit 8586325
Show file tree
Hide file tree
Showing 23 changed files with 582 additions and 1,024 deletions.
1 change: 0 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ module.exports = function (api) {
];

const plugins = [
"date-fns",
["@babel/plugin-proposal-class-properties", { loose: true }],
["@babel/plugin-proposal-logical-assignment-operators", { loose: true }],
["@babel/plugin-proposal-private-property-in-object", { loose: true }],
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@
"@react-aria/interactions": "^3.5.1",
"@react-aria/spinbutton": "3.0.1",
"@react-aria/utils": "3.8.2",
"date-fns": "2.23.0",
"dayjs": "^1.10.6",
"reakit-system": "0.15.1",
"reakit-utils": "0.15.1",
Expand Down Expand Up @@ -147,7 +146,6 @@
"babel-eslint": "10.1.0",
"babel-jest": "^27.1.0",
"babel-loader": "^8.2.2",
"babel-plugin-date-fns": "^2.0.0",
"chalk": "4.1.2",
"codesandbox": "^2.2.3",
"concurrently": "6.2.1",
Expand Down
12 changes: 4 additions & 8 deletions src/calendar/CalendarCellButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ensureFocus, useForkRef } from "reakit-utils";
import { createComponent, createHook } from "reakit-system";
import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit";

import { isInvalidDateRange, isSameDay } from "../utils";
import { isSameDay } from "../utils";
import { CALENDAR_CELL_BUTTON_KEYS } from "./__keys";
import { CalendarStateReturn } from "./CalendarState";
import { RangeCalendarStateReturn } from "./RangeCalendarState";
Expand All @@ -28,14 +28,11 @@ export const useCalendarCellButton = createHook<
isDisabled: isDisabledOption,
date,
month,
minDate,
maxDate,
isInvalidDateRange,
} = options;
const isCurrentMonth = date.getMonth() === month;
const isDisabled =
isDisabledOption ||
!isCurrentMonth ||
isInvalidDateRange(date, minDate, maxDate);
isDisabledOption || !isCurrentMonth || isInvalidDateRange(date);
const truelyDisabled = disabled || isDisabled;

return { disabled: truelyDisabled, ...options };
Expand Down Expand Up @@ -146,11 +143,10 @@ export type CalendarCellButtonOptions = ButtonOptions &
| "setFocusedDate"
| "isDisabled"
| "month"
| "minDate"
| "maxDate"
| "dateValue"
| "isFocused"
| "isRangeCalendar"
| "isInvalidDateRange"
> & {
date: Date;
};
Expand Down
140 changes: 69 additions & 71 deletions src/calendar/CalendarState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
addWeeks,
addYears,
endOfMonth,
format,
formatDate,
getDaysInMonth,
isSameMonth,
startOfDay,
Expand All @@ -19,12 +19,9 @@ import {
subMonths,
subWeeks,
subYears,
parseDate,
stringifyDate,
isInvalidDateRange,
useControllableState,
toUTCString,
} from "../utils";
import { closestTo } from "../utils";
import * as React from "react";
import { unstable_useId as useId } from "reakit";
import { useUpdateEffect } from "@chakra-ui/hooks";
Expand All @@ -38,38 +35,34 @@ export function useCalendarState(
props: CalendarInitialState = {},
): CalendarStateReturn {
const {
value: initialDate,
defaultValue: defaultValueProp,
onChange: onChangeProp,
minValue: minValueProp,
maxValue: maxValueProp,
value: initialValue,
defaultValue = toUTCString(new Date()),
onChange,
minValue,
maxValue,
isDisabled = false,
isReadOnly = false,
autoFocus = false,
} = props;

const onChange = React.useCallback(
(date: Date) => {
return onChangeProp?.(stringifyDate(date));
},
[onChangeProp],
);

const [value, setControllableValue] = useControllableState({
value: parseDate(initialDate),
defaultValue: parseDate(defaultValueProp),
const [value, setValue] = useControllableState({
value: initialValue,
defaultValue,
onChange,
});
const monthFormatter = useDateFormatter({ month: "long", year: "numeric" });

const initialMonth = value ?? new Date();
const minValue = parseDate(minValueProp);
const maxValue = parseDate(maxValueProp);

const [currentMonth, setCurrentMonth] = React.useState(initialMonth);
const [focusedDate, setFocusedDate] = React.useState(initialMonth);
const date = React.useMemo(() => new Date(value), [value]);
const minDateValue = React.useMemo(
() => (minValue ? new Date(minValue) : new Date(-864e13)),
[minValue],
);
const maxDateValue = React.useMemo(
() => (maxValue ? new Date(maxValue) : new Date(864e13)),
[maxValue],
);
const [currentMonth, setCurrentMonth] = React.useState(date);
const [focusedDate, setFocusedDate] = React.useState(date);
const [isFocused, setFocused] = React.useState(autoFocus);

const month = currentMonth.getMonth();
const year = currentMonth.getFullYear();
const weekStart = useWeekStart();
Expand All @@ -89,25 +82,16 @@ export function useCalendarState(
[month, monthStartsAt, weeksInMonth, year],
);

// Sets focus to a specific cell date
function focusCell(date: Date) {
if (isInvalidDateRange(date, minValue, maxValue)) {
// Fixes https://github.com/timelessco/renderlesskit-react/issues/116
// Issue causing the focusNextMonth & focusPrevMonth to not work because
// of adding one month to the current date which becomes invalid above.
if (minValue && maxValue) {
if (!isSameMonth(date, minValue) && !isSameMonth(date, maxValue))
return;
function isInvalidDateRange(value: Date) {
const min = new Date(minDateValue);
const max = new Date(maxDateValue);

const nextDate = closestTo(date, [minValue, maxValue]);
if (!isSameMonth(nextDate, currentMonth)) {
setCurrentMonth(startOfMonth(nextDate).toDate());
}
setFocusedDate(nextDate);
}
return value < min || value > max;
}

return;
}
// Sets focus to a specific cell date
function focusCell(date: Date) {
if (isInvalidDateRange(date)) return;

if (!isSameMonth(date, currentMonth)) {
setCurrentMonth(startOfMonth(date).toDate());
Expand All @@ -118,15 +102,34 @@ export function useCalendarState(

const announceSelectedDate = React.useCallback((value: Date) => {
if (!value) return;
announce(`Selected Date: ${format(value, "do MMM yyyy")}`);

announce(`Selected Date: ${formatDate(value, "do MMM yyyy")}`);
}, []);

function setValue(value: Date) {
if (!isDisabled && !isReadOnly) {
setControllableValue(value);
announceSelectedDate(value);
}
}
const setDate = React.useCallback(
(value: Date) => {
if (!isDisabled && !isReadOnly) {
setValue(toUTCString(value));
announceSelectedDate(value);
}
},
[announceSelectedDate, isDisabled, isReadOnly, setValue],
);

// TODO
// This runs only once when the component is mounted
// Controlled state doesn't change the claender position
// React.useEffect(() => {
// const clampedDate = clamp(date, {
// start: minDateValue,
// end: maxDateValue,
// });
// setDate(clampedDate);
// setCurrentMonth(clampedDate);
// setFocusedDate(clampedDate);
// }, [date, maxDateValue, minDateValue, setDate]);

const monthFormatter = useDateFormatter({ month: "long", year: "numeric" });

// Announce when the current month changes
useUpdateEffect(() => {
Expand All @@ -141,10 +144,9 @@ export function useCalendarState(
const { id: calendarId } = useId({ id: props.id, baseId: "calendar" });

return {
dateValue: date,
setDateValue: setDate,
calendarId,
dateValue: value,
minDate: minValue,
maxDate: maxValue,
month,
year,
weekStart,
Expand All @@ -154,7 +156,6 @@ export function useCalendarState(
isFocused,
isReadOnly,
setFocused,
setDateValue: setValue,
currentMonth,
setCurrentMonth,
focusedDate,
Expand Down Expand Up @@ -191,11 +192,12 @@ export function useCalendarState(
focusCell(subYears(focusedDate, 1));
},
selectFocusedDate() {
setValue(focusedDate);
setDate(focusedDate);
},
selectDate(date: Date) {
setValue(date);
setDate(date);
},
isInvalidDateRange,
isRangeCalendar: false,
};
}
Expand All @@ -209,14 +211,6 @@ export type CalendarState = {
* Selected Date value
*/
dateValue: Date;
/**
* Minimum allowed Date value
*/
minDate: Date | undefined;
/**
* Maximum allowed Date value
*/
maxDate: Date | undefined;
/**
* Month of the current date value
*/
Expand Down Expand Up @@ -260,6 +254,10 @@ export type CalendarState = {
* Date value that is currently focused
*/
focusedDate: Date;
/**
* Informs if the given date is within the min & max date.
*/
isInvalidDateRange: (value: Date) => boolean;
/**
* `true` if the calendar is used as RangeCalendar
*/
Expand Down Expand Up @@ -338,18 +336,18 @@ export type CalendarActions = {
};

type ValueBase = {
/** The current value (controlled). */
/** The current date (controlled). */
value?: string;
/** The default value (uncontrolled). */
/** The default date (uncontrolled). */
defaultValue?: string;
/** Handler that is called when the value changes. */
/** Handler that is called when the date changes. */
onChange?: (value: string) => void;
};

type RangeValueMinMax = {
/** The smallest value allowed. */
/** The lowest date allowed. */
minValue?: string;
/** The largest value allowed. */
/** The highest date allowed. */
maxValue?: string;
};

Expand Down
Loading

0 comments on commit 8586325

Please sign in to comment.