Skip to content

Commit

Permalink
fix(16740): DatePicker calendar close issue on clickAway, DatePicker …
Browse files Browse the repository at this point in the history
…not running onChange events, DatePicker setting and clearing date in range issues (carbon-design-system#17072)

* fix: fixes DatePicker calendar close issue on clickAway

* fix(DatePicker): fixes close calendar issue on click away

* fix: covers empty value conditions

* refactor: updates avt test as per 1.58 version

* refactor: reverts changes made by renovate on avt test

* refactor: removes callback and dependency from useeffect

* refactor: callback is only added to onCalendarClose

* refactor: deprecates the usage is setTimeout to use useEffect

* refactor: revert storybook changes
  • Loading branch information
2nikhiltom authored and tay1orjones committed Aug 9, 2024
1 parent 7e93291 commit 43a514c
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 24 deletions.
2 changes: 1 addition & 1 deletion e2e/components/DatePicker/DatePicker-test.avt.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ test.describe('@avt DatePicker', () => {
await page.keyboard.press('Enter');
await page.keyboard.press('Enter');
await expect(
page.locator('input#date-picker-input-id-finish')
page.locator('input#date-picker-input-id-start')
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).not.toHaveClass(
/open/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ test.describe('@avt FluidDatePicker', () => {
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
await expect(
page.locator('input#date-picker-input-id-finish')
page.locator('input#date-picker-input-id-start')
).toBeFocused();
await expect(page.locator('div.flatpickr-calendar')).not.toHaveClass(
/open/
Expand Down
102 changes: 80 additions & 22 deletions packages/react/src/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,17 @@ const DatePicker = React.forwardRef(function DatePicker(

const lastStartValue = useRef('');

interface CalendarCloseEvent {
selectedDates: Date[];
dateStr: string;
instance: object; //This is `Intance` of flatpicker
}
const [calendarCloseEvent, setCalendarCloseEvent] =
useState<CalendarCloseEvent | null>(null);

// fix datepicker deleting the selectedDate when the calendar closes
const onCalendarClose = (selectedDates, dateStr) => {
endInputField?.current?.focus();
calendarRef?.current?.calendarContainer?.classList.remove('open');
setTimeout(() => {
const handleCalendarClose = useCallback(
(selectedDates, dateStr, instance) => {
if (
lastStartValue.current &&
selectedDates[0] &&
Expand All @@ -461,21 +467,29 @@ const DatePicker = React.forwardRef(function DatePicker(
);
}
if (onClose) {
onClose(
calendarRef.current.selectedDates,
dateStr,
calendarRef.current
);
onClose(selectedDates, dateStr, instance);
}
});
},
[onClose]
);
const onCalendarClose = (selectedDates, dateStr, instance, e) => {
if (e && e.type === 'clickOutside') {
return;
}
setCalendarCloseEvent({ selectedDates, dateStr, instance });
};
useEffect(() => {
if (calendarCloseEvent) {
const { selectedDates, dateStr, instance } = calendarCloseEvent;
handleCalendarClose(selectedDates, dateStr, instance);
setCalendarCloseEvent(null);
}
}, [calendarCloseEvent, handleCalendarClose]);

const endInputField = useRef<HTMLTextAreaElement>(null);
const calendarRef: any | undefined = useRef(null);
const savedOnChange = useSavedCallback(onChange);
const savedOnClose = useSavedCallback(
datePickerType === 'range' ? onCalendarClose : onClose
);

const savedOnOpen = useSavedCallback(onOpen);

const datePickerClasses = cx(`${prefix}--date-picker`, {
Expand Down Expand Up @@ -610,6 +624,7 @@ const DatePicker = React.forwardRef(function DatePicker(
const { current: end } = endInputField;
const flatpickerconfig: any = {
inline: inline ?? false,
onClose: onCalendarClose,
disableMobile: true,
defaultDate: value,
closeOnSelect: closeOnSelect,
Expand Down Expand Up @@ -653,7 +668,7 @@ const DatePicker = React.forwardRef(function DatePicker(
savedOnChange(...args);
}
},
onClose: savedOnClose,

onReady: onHook,
onMonthChange: onHook,
onYearChange: onHook,
Expand Down Expand Up @@ -772,14 +787,7 @@ const DatePicker = React.forwardRef(function DatePicker(
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
savedOnChange,
savedOnClose,
savedOnOpen,
readOnly,
closeOnSelect,
hasInput,
]);
}, [savedOnChange, savedOnOpen, readOnly, closeOnSelect, hasInput]);

// this hook allows consumers to access the flatpickr calendar
// instance for cases where functions like open() or close()
Expand Down Expand Up @@ -831,6 +839,56 @@ const DatePicker = React.forwardRef(function DatePicker(
calendarRef.current.set('inline', inline);
}
}, [inline]);
useEffect(() => {
//when value prop is set to empty, this clears the faltpicker's calendar instance and text input
if (value === '') {
calendarRef.current?.clear();
if (startInputField.current) {
startInputField.current.value = '';
}

if (endInputField.current) {
endInputField.current.value = '';
}
}
}, [value]);

useEffect(() => {
let isMouseDown = false;

const handleMouseDown = (event) => {
if (
calendarRef.current &&
calendarRef.current.isOpen &&
!calendarRef.current.calendarContainer.contains(event.target) &&
!startInputField.current.contains(event.target) &&
!endInputField.current?.contains(event.target)
) {
isMouseDown = true;
// Close the calendar immediately on mousedown
closeCalendar(event);
}
};

const closeCalendar = (event) => {
calendarRef.current.close();
// Remove focus from endDate calendar input
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
onCalendarClose(
calendarRef.current.selectedDates,
'',
calendarRef.current,
{ type: 'clickOutside' }
);
};
document.addEventListener('mousedown', handleMouseDown, true);

return () => {
document.removeEventListener('mousedown', handleMouseDown, true);
};
}, [calendarRef, startInputField, endInputField, onCalendarClose]);

useEffect(() => {
if (calendarRef?.current?.set) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ import { match, keys } from '../../../internal/keyboard';
*/
export default (config) => (fp) => {
const { inputFrom, inputTo, lastStartValue } = config;
/**
* Handles `click` outside to close calendar
*/
const handleClickOutside = (event) => {
if (
!fp.isOpen ||
fp.calendarContainer.contains(event.target) ||
event.target === inputFrom ||
event.target === inputTo
) {
return;
}
fp.close();
};
/**
* Handles `keydown` event.
*/
Expand Down Expand Up @@ -127,6 +141,7 @@ export default (config) => (fp) => {
inputTo.removeEventListener('blur', handleBlur, true);
}
inputFrom.removeEventListener('keydown', handleKeydown, true);
document.removeEventListener('click', handleClickOutside, true);
};

/**
Expand All @@ -140,6 +155,7 @@ export default (config) => (fp) => {
inputTo.addEventListener('keydown', handleKeydown, true);
inputTo.addEventListener('blur', handleBlur, true);
}
document.addEventListener('click', handleClickOutside, true);
};

/**
Expand Down

0 comments on commit 43a514c

Please sign in to comment.