Skip to content

Commit

Permalink
patch: pr7878 (#7896)
Browse files Browse the repository at this point in the history
* feat(DateInput, DateRangeInput): add prop `onCalendarOpenChanged` (#7878)

* feat(DateInput, DateRangeInput): add prop onCalendarClose

* feat(DateInput): replace onCalendarClose to onCalendarOpenChanged

(cherry picked from commit be68ee8)

* test(DateRangeInput): fix test
  • Loading branch information
EldarMuhamethanov authored Nov 5, 2024
1 parent cb2aedc commit af6aa97
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 6 deletions.
23 changes: 23 additions & 0 deletions packages/vkui/src/components/DateInput/DateInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,27 @@ describe('DateInput', () => {

expect(container.contains(document.activeElement)).toBeFalsy();
});

it('should call onCloseCalendar calendar was closed', async () => {
jest.useFakeTimers();
const onCalendarOpenChanged = jest.fn();
const { container } = render(
<DateInput value={date} onCalendarOpenChanged={onCalendarOpenChanged} />,
);
const inputLikes = getInputsLike(container);

const [dates] = inputLikes;

await userEvent.click(dates);
expect(onCalendarOpenChanged).toHaveBeenCalledTimes(1);
expect(onCalendarOpenChanged.mock.calls[0][0]).toBeTruthy();

expect(container.contains(document.activeElement)).toBeTruthy();
await userEvent.click(screen.getByText(`${date.getDate() - 1}`));

expect(onCalendarOpenChanged).toHaveBeenCalledTimes(2);
expect(onCalendarOpenChanged.mock.calls[1][0]).toBeFalsy();

expect(container.contains(document.activeElement)).toBeFalsy();
});
});
3 changes: 3 additions & 0 deletions packages/vkui/src/components/DateInput/DateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface DateInputProps
clearFieldLabel?: string;
showCalendarLabel?: string;
disableCalendar?: boolean;
onCalendarOpenChanged?: (opened: boolean) => void;
}

const elementsConfig = (index: number) => {
Expand Down Expand Up @@ -147,6 +148,7 @@ export const DateInput = ({
nextMonthIcon,
disableCalendar = false,
renderDayContent,
onCalendarOpenChanged,
...props
}: DateInputProps): React.ReactNode => {
const daysRef = React.useRef<HTMLSpanElement>(null);
Expand Down Expand Up @@ -205,6 +207,7 @@ export const DateInput = ({
onInternalValueChange,
getInternalValue,
value,
onCalendarOpenChanged,
});

const { sizeY = 'none' } = useAdaptivity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,27 @@ describe('DateRangeInput', () => {

expect(onChange).toBeCalledTimes(0);
});

it('should call onCalendarClose callback when calendar was closed', async () => {
jest.useFakeTimers();
const onCalendarOpenChanged = jest.fn();
const { container } = render(
<DateRangeInput value={[startDate, endDate]} onCalendarOpenChanged={onCalendarOpenChanged} />,
);
const inputLikes = getInputsLike(container);
const [dates] = inputLikes;

await userEvent.click(dates);

expect(onCalendarOpenChanged).toHaveBeenCalledTimes(1);
expect(onCalendarOpenChanged.mock.calls[0][0]).toBeTruthy();

expect(container.contains(document.activeElement)).toBeTruthy();
await userEvent.click(screen.getAllByText('15')[1]);

expect(onCalendarOpenChanged).toHaveBeenCalledTimes(2);
expect(onCalendarOpenChanged.mock.calls[1][0]).toBeFalsy();

expect(container.contains(document.activeElement)).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface DateRangeInputProps
Omit<FormFieldProps, 'maxHeight'> {
calendarPlacement?: PlacementWithAuto;
closeOnChange?: boolean;
onCalendarOpenChanged?: (opened: boolean) => void;
clearFieldLabel?: string;
showCalendarLabel?: string;
changeStartDayLabel?: string;
Expand Down Expand Up @@ -140,6 +141,7 @@ export const DateRangeInput = ({
prevMonthIcon,
nextMonthIcon,
disableCalendar = false,
onCalendarOpenChanged,
renderDayContent,
...props
}: DateRangeInputProps): React.ReactNode => {
Expand Down Expand Up @@ -221,6 +223,7 @@ export const DateRangeInput = ({
onInternalValueChange,
getInternalValue,
value,
onCalendarOpenChanged,
});

const { sizeY = 'none' } = useAdaptivity();
Expand Down
29 changes: 23 additions & 6 deletions packages/vkui/src/hooks/useDateInput.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useCallback } from 'react';
import * as React from 'react';
import { useDOM } from '../lib/dom';
import { useBooleanState } from './useBooleanState';
Expand All @@ -17,6 +18,7 @@ export interface UseDateInputDependencies<T, D> {
onInternalValueChange: (value: string[]) => void;
getInternalValue: (value?: D | undefined) => string[];
onChange?: (value?: D | undefined) => void;
onCalendarOpenChanged?: (opened: boolean) => void;
}

export function useDateInput<T extends HTMLElement, D>({
Expand All @@ -29,6 +31,7 @@ export function useDateInput<T extends HTMLElement, D>({
onInternalValueChange,
getInternalValue,
value,
onCalendarOpenChanged,
}: UseDateInputDependencies<T, D>): {
rootRef: React.RefObject<HTMLDivElement>;
calendarRef: React.RefObject<HTMLDivElement>;
Expand All @@ -51,14 +54,28 @@ export function useDateInput<T extends HTMLElement, D>({
const [focusedElement, setFocusedElement] = React.useState<number | null>(null);
const { window } = useDOM();

const _onCalendarClose = useCallback(() => {
if (open) {
closeCalendar();
onCalendarOpenChanged?.(false);
}
}, [closeCalendar, onCalendarOpenChanged, open]);

const _onCalendarOpen = useCallback(() => {
if (!open) {
openCalendar();
onCalendarOpenChanged?.(true);
}
}, [onCalendarOpenChanged, open, openCalendar]);

const removeFocusFromField = React.useCallback(() => {
if (focusedElement !== null) {
setFocusedElement(null);
closeCalendar();
_onCalendarClose();
window!.getSelection()?.removeAllRanges();
setInternalValue(getInternalValue(value));
}
}, [focusedElement, closeCalendar, getInternalValue, value, window]);
}, [focusedElement, _onCalendarClose, window, getInternalValue, value]);

const handleClickOutside = React.useCallback(
(e: MouseEvent) => {
Expand Down Expand Up @@ -101,14 +118,14 @@ export function useDateInput<T extends HTMLElement, D>({

if (element) {
element.focus();
openCalendar();
_onCalendarOpen();
range.selectNodeContents(element as Node);

const selection = window!.getSelection();
selection?.removeAllRanges();
selection?.addRange(range);
}
}, [disabled, focusedElement, openCalendar, refs, window]);
}, [disabled, focusedElement, _onCalendarOpen, refs, window]);

const clear = React.useCallback(() => {
onChange?.(undefined);
Expand Down Expand Up @@ -190,8 +207,8 @@ export function useDateInput<T extends HTMLElement, D>({
rootRef,
calendarRef,
open,
openCalendar,
closeCalendar,
openCalendar: _onCalendarOpen,
closeCalendar: _onCalendarClose,
internalValue,
focusedElement,
setFocusedElement,
Expand Down

0 comments on commit af6aa97

Please sign in to comment.