Skip to content

Commit dcda1c5

Browse files
author
Ruslan Farkhutdinov
committed
Popover: Support all hover hide event types & fix default delay issue
1 parent 68fd721 commit dcda1c5

1 file changed

Lines changed: 32 additions & 12 deletions

File tree

packages/devextreme/js/__internal/ui/popover/m_popover.ts

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,24 @@ const POSITION_FLIP_MAP = {
4747
center: 'center',
4848
};
4949

50-
const HOVER_HIDE_EVENTS = ['mouseleave', 'mouseout'];
50+
const HOVER_EVENT_PAIRS: Record<string, string> = {
51+
// eslint-disable-next-line spellcheck/spell-checker
52+
mouseleave: 'mouseenter',
53+
// eslint-disable-next-line spellcheck/spell-checker
54+
mouseout: 'mouseover',
55+
// eslint-disable-next-line spellcheck/spell-checker
56+
pointerleave: 'pointerenter',
57+
// eslint-disable-next-line spellcheck/spell-checker
58+
dxhoverend: 'dxhoverstart',
59+
};
60+
61+
const HOVER_HIDE_EVENTS = Object.keys(HOVER_EVENT_PAIRS);
5162
const HOVER_HIDE_DELAY = 50;
5263

5364
const ESC_KEY_NAME = 'escape';
5465

5566
type PopoverTarget = string | dxElementWrapper | Element | undefined;
67+
type PopoverEventOption = 'showEvent' | 'hideEvent';
5668

5769
export interface PopoverProperties extends Omit<Properties,
5870
'onTitleRendered' | 'onHidden' | 'onHiding' | 'onShowing' | 'onShown'
@@ -237,8 +249,14 @@ class Popover<
237249
}
238250

239251
const namespace = `${this.NAME as string}Hoverable`;
240-
const hoverInEventName = addNamespace('mouseenter', namespace);
241-
const hoverOutEventName = addNamespace('mouseleave', namespace);
252+
const activeHideEvents = hideEventName.split(/\s+/).filter((eventName: string) => eventName in HOVER_EVENT_PAIRS);
253+
254+
const hoverInEventName = activeHideEvents
255+
.map((eventName: string) => addNamespace(HOVER_EVENT_PAIRS[eventName], namespace))
256+
.join(' ');
257+
const hoverOutEventName = activeHideEvents
258+
.map((eventName: string) => addNamespace(eventName, namespace))
259+
.join(' ');
242260

243261
eventsEngine.off($overlayContent, hoverInEventName);
244262
eventsEngine.on($overlayContent, hoverInEventName, () => {
@@ -264,19 +282,21 @@ class Popover<
264282
return;
265283
}
266284
const namespace = `${this.NAME as string}Hoverable`;
267-
eventsEngine.off($overlayContent, addNamespace('mouseenter', namespace));
268-
eventsEngine.off($overlayContent, addNamespace('mouseleave', namespace));
285+
const allEventNames = [
286+
...Object.keys(HOVER_EVENT_PAIRS),
287+
...Object.values(HOVER_EVENT_PAIRS),
288+
].map((e) => addNamespace(e, namespace)).join(' ');
289+
eventsEngine.off($overlayContent, allEventNames);
269290
}
270291

271292
_createEventHandler(name: string) {
272293
const action = this._createAction(() => {
273-
const explicitDelay = this._getEventDelay(`${name}Event`);
294+
const explicitDelay = this._getEventDelay(`${name}Event` as PopoverEventOption);
274295
this._clearEventsTimeouts();
275296

276297
const hideEventName = name === 'hide' ? this._getEventName('hideEvent') : null;
277298
const isHoverHide = hideEventName && this._isHoverHideEventName(hideEventName);
278-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
279-
const delay = explicitDelay || (isHoverHide ? HOVER_HIDE_DELAY : 0);
299+
const delay = explicitDelay ?? (isHoverHide ? HOVER_HIDE_DELAY : 0);
280300

281301
if (delay) {
282302
this._timeouts[name] = setTimeout(() => {
@@ -355,10 +375,10 @@ class Popover<
355375
return this._getEventNameByOption(optionValue);
356376
}
357377

358-
_getEventDelay(optionName) {
359-
const optionValue = this.option(optionName);
360-
// @ts-expect-error
361-
return isObject(optionValue) && optionValue.delay;
378+
_getEventDelay(optionName: PopoverEventOption): number | undefined {
379+
const { [optionName]: optionValue } = this.option();
380+
381+
return isObject(optionValue) ? (optionValue.delay) : undefined;
362382
}
363383

364384
_renderArrow(): void {

0 commit comments

Comments
 (0)