Skip to content

Commit

Permalink
feat(useFloatingWithInteractions): extend API (#6166)
Browse files Browse the repository at this point in the history
<!-- Чеклист. Лишние пункты можно удалить если изменения не подразумевают их наличие. Иначе, необходимо обоснование по каждому пункту. -->
- [x] Unit-тесты

h2. Описание

- Для `onShownChange` добавляем второй аргумент `reason`, чтобы у пользователя появилась возможность закрывать/открывать всплывающий в зависимости от причины. Создаём тип `OnShownChange`.
- Явно объявляем результат работы хука `UseFloatingWithInteractionsReturn`.
- Удаляем неиспользуемый тип `content` из параметров.
- Добавляем метод `onClose()`, чтобы была возможность программно закрыть всплывающий элемент. Это новый тип в `ShownChangeReason` `'callback'`. У пользователя будет возможность прокинуть метод куда-то в дочерний элемент и т.п..

h2. Изменения

1. Обмазал все `expect`  хелпером [`waitFor`](https://testing-library.com/docs/dom-testing-library/api-async/#waitfor) – она позволяет дождаться выполнения `setTimeout(fn, 0)`.
2. За счёт п.1 получилось убрать в `FocusTrap` хак для тестов.
    https://github.com/VKCOM/VKUI/blob/b15b2451d463d202e76f035de2e360ef7b43befb/packages/vkui/src/components/FocusTrap/FocusTrap.tsx#L112-L116
3. То, что не покрыть тестами заигнорил через `/* istanbul ignore <word>[non-word] [optional-docs] */` (см. [доку](https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md))
  • Loading branch information
inomdzhon authored Nov 30, 2023
1 parent fb81a0b commit f6a66ee
Show file tree
Hide file tree
Showing 7 changed files with 376 additions and 125 deletions.
12 changes: 2 additions & 10 deletions packages/vkui/src/components/FocusTrap/FocusTrap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,11 @@ export const FocusTrap = <T extends HTMLElement = HTMLElement>({
return;
}

const focusTo = () => {
setTimeout(() => {
if (restoreFocusTo) {
restoreFocusTo.focus();
}
};

// В Jest не срабатывает setTimeout из функции очистки эффекта, поэтому для тестов вызываем
// сразу (см. useFloatingWithInteractions())
if (process.env.NODE_ENV === 'test') {
focusTo();
}

setTimeout(focusTo, timeout);
}, timeout);
};
},
[restoreFocus, timeout],
Expand Down
10 changes: 9 additions & 1 deletion packages/vkui/src/lib/floating/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { Placement } from '@vkontakte/vkui-floating-ui/react-dom';
import type {
Placement,
ReferenceType,
UseFloatingReturn,
} from '@vkontakte/vkui-floating-ui/react-dom';

export type AutoPlacementType = 'auto' | 'auto-start' | 'auto-end';

Expand All @@ -8,8 +12,12 @@ export type {
UseFloatingOptions,
ReferenceType,
ArrowOptions,
UseFloatingReturn,
Placement,
Middleware as UseFloatingMiddleware,
UseFloatingData,
Strategy as FloatingPositionStrategy,
} from '@vkontakte/vkui-floating-ui/react-dom';

export type UseFloatingRefs<RT extends ReferenceType = ReferenceType> =
UseFloatingReturn<RT>['refs'];
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`useFloatingWithInteractions tests with snapshot should be hidden state
"onMouseOver": [Function],
"style": {},
},
"onClose": [Function],
"onEscapeKeyDown": undefined,
"onRestoreFocus": [Function],
"placement": "bottom",
Expand Down Expand Up @@ -48,6 +49,7 @@ exports[`useFloatingWithInteractions tests with snapshot should be shown state 1
"width": "max-content",
},
},
"onClose": [Function],
"onEscapeKeyDown": [Function],
"onRestoreFocus": [Function],
"placement": "bottom",
Expand Down Expand Up @@ -89,6 +91,7 @@ exports[`useFloatingWithInteractions tests with snapshot should be shown state w
"width": "max-content",
},
},
"onClose": [Function],
"onEscapeKeyDown": undefined,
"onRestoreFocus": [Function],
"placement": "bottom",
Expand Down Expand Up @@ -129,6 +132,7 @@ exports[`useFloatingWithInteractions tests with snapshot should be shown state w
"width": "max-content",
},
},
"onClose": [Function],
"onEscapeKeyDown": [Function],
"onRestoreFocus": [Function],
"placement": "bottom",
Expand Down Expand Up @@ -159,6 +163,7 @@ exports[`useFloatingWithInteractions tests with snapshot should return default v
"floatingProps": {
"style": {},
},
"onClose": [Function],
"onEscapeKeyDown": undefined,
"onRestoreFocus": [Function],
"placement": "bottom",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export { useFloatingWithInteractions } from './useFloatingWithInteractions';

export type { UseFloatingWithInteractionsProps } from './types';
export type {
OnShownChange,
UseFloatingWithInteractionsProps,
UseFloatingWithInteractionsReturn,
} from './types';

export { DEFAULT_TRIGGER } from './constants';
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Placement, UseFloatingRefs } from '../types';
import type { UseFloatingMiddlewaresBootstrapOptions } from '../useFloatingMiddlewaresBootstrap';

export type InteractiveTriggerType = 'click' | 'hover' | 'focus';
Expand All @@ -6,7 +7,15 @@ export type ManualTriggerType = 'manual';

export type TriggerType = ManualTriggerType | InteractiveTriggerType | InteractiveTriggerType[];

export type ShownChangeReason = 'click-outside' | 'escape-key' | 'click' | 'hover' | 'focus';
export type ShownChangeReason =
| 'click-outside'
| 'escape-key'
| 'click'
| 'hover'
| 'focus'
| 'callback';

export type OnShownChange = (shown: boolean, reason?: ShownChangeReason) => void;

export interface UseFloatingWithInteractionsProps
extends Pick<
Expand Down Expand Up @@ -35,10 +44,6 @@ export interface UseFloatingWithInteractionsProps
* > Используется только для `trigger="hover"`.
*/
hoverDelay?: number | [number, number];
/**
* Содержимое всплывающего окна.
*/
content?: React.ReactNode;
/**
* Блокирует изменение состояния.
*/
Expand Down Expand Up @@ -66,7 +71,7 @@ export interface UseFloatingWithInteractionsProps
/**
* Вызывается при каждом изменении видимости всплывающего окна.
*/
onShownChange?(shown: boolean): void;
onShownChange?: OnShownChange;
}

export type ReferenceProps<T = HTMLElement> = Omit<
Expand All @@ -82,3 +87,15 @@ export type FloatingProps<T = HTMLElement> = Omit<
React.DOMAttributes<T>,
'onMouseOver' | 'onMouseLeave' | 'onClick' | 'onAnimationStart' | 'onAnimationEnd'
>;

export interface UseFloatingWithInteractionsReturn<T extends HTMLElement = HTMLElement> {
placement: Placement;
shown: boolean;
willBeHide: boolean;
refs: UseFloatingRefs<T>;
referenceProps: ReferenceProps<T>;
floatingProps: FloatingProps<T>;
onClose(this: void): void;
onEscapeKeyDown?(this: void): void;
onRestoreFocus(this: void): boolean;
}
Loading

0 comments on commit f6a66ee

Please sign in to comment.