Skip to content

Commit

Permalink
improve hover state logic, fix sticky bugs etc
Browse files Browse the repository at this point in the history
  • Loading branch information
stowball committed Dec 19, 2024
1 parent cef519b commit 01e5bd9
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 11 deletions.
45 changes: 43 additions & 2 deletions packages/react/src/date-picker/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useCallback,
useMemo,
useRef,
// Profiler,
} from 'react';
import FocusLock from 'react-focus-lock';
import {
Expand All @@ -32,6 +33,7 @@ import {
startOfWeek,
type Locale,
} from 'date-fns';
import { DebouncedState } from 'use-debounce';
import { boxPalette, mapSpacing, tokens, useId } from '../core';
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from '../icon';
import { Box } from '../box';
Expand Down Expand Up @@ -86,12 +88,14 @@ export type CalendarRangeProps = Omit<
// returnFocusRef?: RefObject<HTMLButtonElement>;
inputMode?: 'from' | 'to';
onHover?: (date: Date) => void;
clearHoveredDay?: DebouncedState<() => void>;
};

export function CalendarRange({
// returnFocusRef,
inputMode,
onHover,
clearHoveredDay,
...props
}: CalendarRangeProps) {
// console.log(`props`, props);
Expand Down Expand Up @@ -160,17 +164,53 @@ export function CalendarRange({
// data-in-range={activeModifiers.qux}
// data-day-after-from={props.date > selectedDays?.from}
// data-day-before-to={props.date < selectedDays?.to}
onMouseEnter={onHover ? () => onHover(props.date) : undefined}
>
{/* Without this focusable span, left and right do not work in screen readers */}
<span tabIndex={-1}>{isHidden ? undefined : children}</span>
<span
tabIndex={-1}
onMouseLeave={() => {
// console.log(`props.date`, props.date);
// console.log(`e`, e);
!isHidden && clearHoveredDay?.();
}}
onMouseEnter={
onHover && !isHidden
? () => {
clearHoveredDay?.cancel();
onHover(props.date);
}
: undefined
}
css={{
position: 'relative',
display: 'flex',
height: '3rem',
width: '3rem',
justifyContent: 'center',
alignItems: 'center',
'::before': {
content: '""',
position: 'absolute',
inset: 0,
// background: 'rgba(255,0,0,0.2)',
},
}}
>
{isHidden ? undefined : children}
</span>
</td>
);
},
},
};

return (
// <Profiler
// id="cal"
// onRender={(id, phase, duration) => {
// console.log(id, phase, duration);
// }}
// >
<FocusLock
autoFocus={false}
// onDeactivation={() => {
Expand All @@ -183,6 +223,7 @@ export function CalendarRange({
<DayPicker mode="range" {...combinedDayPickerProps} {...props} />
</CalendarRangeContainer>
</FocusLock>
// {/* </Profiler> */}
);
}

Expand Down
67 changes: 58 additions & 9 deletions packages/react/src/date-range-picker/DateRangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import {
useState,
useEffect,
useMemo,
// Profiler,
} from 'react';
import { SelectRangeEventHandler } from 'react-day-picker';
import { addDays, isAfter, isBefore } from 'date-fns';
import { useDebouncedCallback } from 'use-debounce';
import { Box } from '../box';
import { Flex } from '../flex';
import { Stack } from '../stack';
Expand Down Expand Up @@ -243,6 +245,7 @@ export const DateRangePicker = ({
);

if ((range.from || fromInputValue) && (range.to || toInputValue)) {
setHoveredDay(undefined);
closeCalendar();
return;
}
Expand Down Expand Up @@ -443,10 +446,13 @@ export const DateRangePicker = ({
? getRange(valueAsDateOrUndefined.from, hoveredDay)
: inputMode === 'from'
? getRange(hoveredDay, valueAsDateOrUndefined.from)
: [],
: {},
[hoveredDay, inputMode, valueAsDateOrUndefined]
);
// console.log(`range()`, range());

const clearHoveredDay = useDebouncedCallback(() => {
setHoveredDay(undefined);
}, 200);

// These prop objects serve as a single source of truth for the duplicated Popovers and Calendars below
// We duplicate the Popover + Calendar as a workaround for a bug that scrolls the page to the top on initial open of the calendar - https://github.com/gpbl/react-day-picker/discussions/2059
Expand All @@ -462,13 +468,25 @@ export const DateRangePicker = ({
returnFocusRef: inputMode === 'from' ? fromTriggerRef : toTriggerRef,
selected: valueAsDateOrUndefined,
modifiers: {
// fromRange: (day: Date) => {
// // console.log(`day`, day);
// return fromRange().some(
// (r) => r.toDateString() === day.toDateString()
// );
// // return range().includes(day);
// },
fromRange: (day: Date) => {
// console.log(`day`, day);
return fromRange().some(
(r) => r.toDateString() === day.toDateString()
);
// console.log(`fromRange()`, fromRange());
return fromRange()[day.toDateString()];
// return range().includes(day);
},
// fromRange: (day: Date) => {
// // console.log(`day`, day);
// // console.log(`fromRange()`, fromRange());
// return fromRange().has(day.toDateString());
// // return range().includes(day);
// },
// qux: range(),
// foo: hoveredDay,
},
Expand All @@ -477,10 +495,12 @@ export const DateRangePicker = ({
// foo: 'baz',
},
onHover,
clearHoveredDay,
}),
[
defaultMonth,
disabledCalendarDays,
clearHoveredDay,
// hoveredDay,
inputMode,
numberOfMonths,
Expand All @@ -492,6 +512,12 @@ export const DateRangePicker = ({
);

return (
// <Profiler
// id="drp"
// onRender={(id, phase, duration) => {
// console.log(id, phase, duration);
// }}
// >
<FieldContainer invalid={invalid} id={fieldsetId}>
<Box as="fieldset">
{/* Legend needs to be the first element, so if none is supplied render a visually hidden element. */}
Expand Down Expand Up @@ -584,6 +610,7 @@ export const DateRangePicker = ({
</CalendarProvider>
</Box>
</FieldContainer>
// </Profiler>
);
};

Expand All @@ -598,15 +625,37 @@ export function useDateRangePickerIds(idProp?: string) {
}

const getRange = (startDate?: Date, endDate?: Date) => {
// if (startDate && endDate) {
// const range = [];
// let current = addDays(startDate, 1);
// while (current < endDate) {
// // console.log(`current, hoverDate`, current, hoverDate);
// range.push(current);
// current = addDays(current, 1);
// }
// return range;
// }
// return [];
// const range = new Set();
// if (startDate && endDate) {
// // const range = [];
// let current = addDays(startDate, 1);
// while (current < endDate) {
// // console.log(`current, hoverDate`, current, hoverDate);
// range.add(current.toDateString());
// current = addDays(current, 1);
// }
// }
// return range;
const range: Record<string, boolean> = {};
if (startDate && endDate) {
const range = [];
let current = addDays(startDate, 1);
while (current < endDate) {
// console.log(`current, hoverDate`, current, hoverDate);
range.push(current);
range[current.toDateString()] = true;
current = addDays(current, 1);
}
return range;
}
return [];
return range;
// return {};
};

0 comments on commit 01e5bd9

Please sign in to comment.