Skip to content

Commit

Permalink
refactor: improved types & fixed bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
anuraghazra committed Sep 22, 2020
1 parent 440e616 commit 2a7ef74
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 48 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@react-aria/interactions": "3.2.0",
"@react-aria/link": "3.1.1",
"@react-aria/utils": "3.2.1",
"@react-aria/visually-hidden": "^3.2.0",
"@react-stately/toggle": "3.2.0",
"date-fns": "^2.16.1",
"react-use-gesture": "7.0.16",
Expand Down
26 changes: 13 additions & 13 deletions src/calendar-v1/CalendarCell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* We improved the Calendar from Aria [useCalendarBase](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/calendar/src/useCalendarBase.ts)
* to work with Reakit System
*/
import { isWeekend } from "date-fns";
import { ariaAttr } from "@chakra-ui/utils";
import { isSameDay, isWeekend } from "date-fns";
import { BoxHTMLProps, BoxOptions, useBox } from "reakit";
import { createComponent, createHook } from "reakit-system";

Expand All @@ -13,9 +13,9 @@ import { CalendarStateReturn } from "./CalendarState";
import { RangeCalendarStateReturn } from "./CalendarRangeState";

export type CalendarCellOptions = BoxOptions &
Pick<
RangeCalendarStateReturn & CalendarStateReturn,
"dateValue" | "getCellOptions" | "highlightDate"
Pick<CalendarStateReturn, "dateValue" | "isDisabled"> &
Partial<
Pick<RangeCalendarStateReturn, "highlightDate" | "getCellOptions">
> & {
weekIndex: number;
dayIndex: number;
Expand All @@ -35,25 +35,25 @@ export const useCalendarCell = createHook<
keys: CALENDAR_CELL_KEYS,

useProps(
{ date, getCellOptions, weekIndex, dayIndex, highlightDate },
{ date, getCellOptions, weekIndex, dayIndex, highlightDate, isDisabled },
htmlProps,
) {
const cellProps = getCellOptions(weekIndex, dayIndex);
const cellProps = getCellOptions?.(weekIndex, dayIndex);

const onMouseEnter = () => {
highlightDate && highlightDate(date);
};

return {
onMouseEnter,
onMouseEnter: isDisabled ? () => {} : onMouseEnter,
role: "gridcell",
"data-is-range-start": cellProps.isRangeStart,
"data-is-range-end": cellProps.isRangeEnd,
"data-is-range-selection": cellProps.isRangeSelection,
"data-is-selection-start": cellProps.isSelectionStart,
"data-is-selection-end": cellProps.isSelectionEnd,
"data-weekend": isWeekend(date),
"aria-selected": ariaAttr(cellProps.isSelected),
"aria-selected": ariaAttr(cellProps?.isSelected),
"data-is-range-end": cellProps?.isRangeEnd,
"data-is-range-start": cellProps?.isRangeStart,
"data-is-selection-end": cellProps?.isSelectionEnd,
"data-is-selection-start": cellProps?.isSelectionStart,
"data-is-range-selection": cellProps?.isRangeSelection,
...htmlProps,
};
},
Expand Down
25 changes: 24 additions & 1 deletion src/calendar-v1/CalendarCellButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ButtonHTMLProps, ButtonOptions, useButton } from "reakit";
import { isInvalid } from "./__utils";
import { CALENDAR_CELL_BUTTON_KEYS } from "./__keys";
import { CalendarStateReturn } from "./CalendarState";
import { RangeCalendarStateReturn } from "./CalendarRangeState";

export type CalendarCellButtonOptions = ButtonOptions &
Pick<
Expand All @@ -27,7 +28,8 @@ export type CalendarCellButtonOptions = ButtonOptions &
| "maxDate"
| "dateValue"
| "isFocused"
> & {
> &
Partial<Pick<RangeCalendarStateReturn, "anchorDate">> & {
date: Date;
};

Expand Down Expand Up @@ -69,7 +71,9 @@ export const useCalendarCellButton = createHook<
disabled,
dateValue,
selectDate,
anchorDate,
focusedDate,
isDisabled,
setFocusedDate,
isFocused: isFocusedOption,
} = options;
Expand Down Expand Up @@ -124,6 +128,25 @@ export const useCalendarCellButton = createHook<
ariaLabel = `${ariaLabel} selected`;
}

// When a cell is focused and this is a range calendar, add a prompt to help
// screenreader users know that they are in a range selection mode.
if (anchorDate && isFocused && !isDisabled) {
let rangeSelectionPrompt = "";

// If selection has started add "click to finish selecting range"
if (anchorDate) {
rangeSelectionPrompt = "click to finish selecting range";
// Otherwise, add "click to start selecting range" prompt
} else {
rangeSelectionPrompt = "click to start selecting range";
}

// Append to aria-label
if (rangeSelectionPrompt) {
ariaLabel = `${ariaLabel} (${rangeSelectionPrompt})`;
}
}

return {
children: useDateFormatter({ day: "numeric" }).format(date),
tabIndex,
Expand Down
28 changes: 24 additions & 4 deletions src/calendar-v1/CalendarRangeState.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { useState } from "react";
import { DateValue } from "./CalendarState";
import { RangeValue } from "@react-types/shared";
import { useCalendarState } from "./CalendarState";
import { endOfDay, getDaysInMonth, isSameDay, startOfDay } from "date-fns";
import { RangeCalendarProps } from "./index.d";
import { useControllableState } from "@chakra-ui/hooks";
import { DateValue, RangeCalendarProps } from "./index.d";
import { useControllableState, useUpdateEffect } from "@chakra-ui/hooks";
import {
format,
endOfDay,
isSameDay,
startOfDay,
getDaysInMonth,
} from "date-fns";
import { announce } from "../utils/LiveAnnouncer";

export function useRangeCalendarState(props: RangeCalendarProps) {
const {
Expand Down Expand Up @@ -43,6 +49,19 @@ export function useRangeCalendarState(props: RangeCalendarProps) {
}
};

useUpdateEffect(() => {
if (anchorDate) return;
if (isSameDay(highlightedRange.start, highlightedRange.end)) return;
if (highlightedRange) {
announce(
`Selected range, from ${format(
highlightedRange.start,
"do MMM yyyy",
)} to ${format(highlightedRange.end, "do MMM yyyy")}`,
);
}
}, [highlightedRange]);

return {
...calendar,
value: dateRange,
Expand All @@ -65,6 +84,7 @@ export function useRangeCalendarState(props: RangeCalendarProps) {
highlightedRange &&
opts.cellDate >= highlightedRange.start &&
opts.cellDate <= highlightedRange.end;

return {
...opts,
isRangeSelection: isSelected,
Expand Down
4 changes: 1 addition & 3 deletions src/calendar-v1/CalendarState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ import {
subYears,
} from "date-fns";

import { CalendarProps } from "./index.d";
import { useWeekStart } from "./useWeekStart";
import { isInvalid, useWeekDays } from "./__utils";
import { CalendarProps } from "./index.d";

export type DateValue = string | number | Date;

export interface IUseCalendarProps extends CalendarProps {
id?: string;
Expand Down
28 changes: 8 additions & 20 deletions src/calendar-v1/RangeCalendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,30 @@
* We improved the Calendar from Aria [useCalendarBase](https://github.com/adobe/react-spectrum/blob/main/packages/%40react-aria/calendar/src/useCalendarBase.ts)
* to work with Reakit System
*/
import { BoxHTMLProps, BoxOptions } from "reakit";
import { BoxOptions } from "reakit";
import { createComponent, createHook } from "reakit-system";

import { CALENDAR_KEYS, RANGE_CALENDAR_KEYS } from "./__keys";
import { RANGE_CALENDAR_KEYS } from "./__keys";
import { RangeCalendarStateReturn } from "./CalendarRangeState";
import {
CalendarHTMLProps,
CalendarOptions,
CalendarProps,
useCalendar,
} from "./Calendar";
import { CalendarHTMLProps, CalendarOptions, useCalendar } from "./Calendar";

export type RangeCalendarOptions = BoxOptions &
CalendarOptions &
Pick<
RangeCalendarStateReturn,
"calendarId" | "setAnchorDate" | "highlightedRange" | "anchorDate"
>;
Pick<RangeCalendarStateReturn, "setAnchorDate">;

export type RangeCalendarHTMLProps = BoxHTMLProps & CalendarHTMLProps;
export type RangeCalendarHTMLProps = CalendarHTMLProps;

export type RangeCalendarProps = CalendarProps &
RangeCalendarOptions &
RangeCalendarHTMLProps;
export type RangeCalendarProps = RangeCalendarOptions & RangeCalendarHTMLProps;

export const useRangeCalendar = createHook<
RangeCalendarOptions,
RangeCalendarHTMLProps
>({
name: "RangeCalendar",
compose: [useCalendar],
compose: useCalendar,
keys: RANGE_CALENDAR_KEYS,

useProps({ setAnchorDate, highlightedRange }, htmlProps) {
const { start, end } = highlightedRange || { start: null, end: null };

useProps({ setAnchorDate }, htmlProps) {
const onKeyDown = (e: any) => {
switch (e.key) {
case "Escape":
Expand Down
7 changes: 1 addition & 6 deletions src/calendar-v1/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
DOMProps,
RangeValue,
StyleProps,
ValueBase,
} from "@react-types/shared";
import { RangeValue, ValueBase } from "@react-types/shared";

export type DateValue = string | number | Date;
export interface CalendarPropsBase {
Expand Down
2 changes: 2 additions & 0 deletions src/calendar-v1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ export * from "./Calendar";
export * from "./CalendarCell";
export * from "./CalendarCellButton";
export * from "./CalendarState";
export * from "./CalendarRangeState";
export * from "./CalendarButton";
export * from "./CalendarGrid";
export * from "./CalendarHeader";
export * from "./CalendarWeekTitle";
export { DateValue } from "./index.d";
9 changes: 8 additions & 1 deletion src/calendar-v1/stories/Calendar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,14 @@ const CalendarComp: React.FC<IUseCalendarProps> = props => {
{state.daysInMonth.map((week, weekIndex) => (
<tr key={weekIndex}>
{week.map((day, dayIndex) => (
<CalendarCell {...state} as="td" key={dayIndex} date={day}>
<CalendarCell
{...state}
as="td"
key={dayIndex}
date={day}
dayIndex={dayIndex}
weekIndex={weekIndex}
>
<CalendarCellButton {...state} date={day} />
</CalendarCell>
))}
Expand Down
Loading

0 comments on commit 2a7ef74

Please sign in to comment.