3 Commits

3 changed files with 59 additions and 25 deletions

View File

@@ -1,3 +1,8 @@
## v6.0.0
- Корректная работа сообытий mouseenter/mouseleave на тач-устройствах
- Предовтращаем лишние показы всплывающей подсказки
## v5.0.0
- Регистрируем сообытия mouseenter/mouseleave на тач-устройствах

View File

@@ -13,8 +13,13 @@ const handleVisibilityChange = () => {
if (document.hidden) {
// Скрываем все активные всплывающие подсказки
for (const $tooltip of document.querySelectorAll('.tooltip')) {
if ($tooltip._reference?._tooltip?.isVisible) {
$tooltip._reference._tooltip.hide({ immediately: true });
const ref = $tooltip._reference;
if (ref?._tooltip) {
// Очищаем таймеры появления при скрытии страницы
clearTimeout(ref._tooltip._showTimeout);
if (ref._tooltip.isVisible) {
ref._tooltip.hide({ immediately: true });
}
}
}
}
@@ -53,8 +58,6 @@ export const createTooltip = ($el, content, options) => {
}
}
let showTimeout;
let hideTimeout;
let rafId;
const listeners = [];
@@ -65,6 +68,8 @@ export const createTooltip = ($el, content, options) => {
$container: undefined,
$arrow: undefined,
$interactive: undefined,
_showTimeout: undefined,
_hideTimeout: undefined,
autoUpdateCleanup: () => {},
setContent(updatedContent) {
@@ -162,8 +167,8 @@ export const createTooltip = ($el, content, options) => {
return;
}
clearTimeout(showTimeout);
clearTimeout(hideTimeout);
clearTimeout($el._tooltip._showTimeout);
clearTimeout($el._tooltip._hideTimeout);
cancelAnimationFrame(rafId);
$el._tooltip.$tooltip?.remove();
@@ -187,7 +192,7 @@ export const createTooltip = ($el, content, options) => {
}
$el._tooltip.show = async ({ immediately } = {}) => {
clearTimeout(hideTimeout);
clearTimeout($el._tooltip._hideTimeout);
if (!$el._tooltip.$tooltip) {
const { computePosition, offset, flip, shift, arrow } = await import('@floating-ui/dom');
@@ -294,10 +299,18 @@ export const createTooltip = ($el, content, options) => {
const { autoUpdate } = await import('@floating-ui/dom');
showTimeout = setTimeout(
$el._tooltip._showTimeout = setTimeout(
async () => {
// Проверяем $el._tooltip на сущестование
if (!$el._tooltip || $el._tooltip.isVisible) {
const isMouseEnterTrigger = options.trigger.includes('mouseenter');
const isHovering = $el.matches(':hover');
// Проверяем $el._tooltip на сущестование и актуальность показа всплывающей подсказки
if (
!$el._tooltip ||
$el._tooltip.isVisible ||
(isMouseEnterTrigger && !isHovering) ||
document.hidden
) {
return;
}
@@ -334,8 +347,8 @@ export const createTooltip = ($el, content, options) => {
};
$el._tooltip.hide = ({ immediately } = {}) => {
clearTimeout(showTimeout);
hideTimeout = setTimeout(
clearTimeout($el._tooltip._showTimeout);
$el._tooltip._hideTimeout = setTimeout(
async () => {
// Проверяем $el._tooltip на сущестование
if (!$el._tooltip || !$el._tooltip.isVisible) {
@@ -395,21 +408,34 @@ export const createTooltip = ($el, content, options) => {
};
$el._tooltip.clickListener = () => {
if (document.hidden) {
return;
}
if (!$el._tooltip.isVisible) {
$el._tooltip.show();
}
};
$el._tooltip.mouseEnterListener = () => {
$el._tooltip.mouseEnterListener = (event) => {
if (event.pointerType !== 'mouse' || document.hidden) {
return;
}
$el._tooltip.show();
};
$el._tooltip.mouseLeaveListener = ({ relatedTarget }) => {
if (options.interactive && relatedTarget && $el._tooltip.$tooltip?.contains(relatedTarget)) {
$el._tooltip.mouseLeaveListener = (event) => {
if (event.pointerType !== 'mouse') {
return;
}
if (options.interactive && event.relatedTarget && $el._tooltip.$tooltip?.contains(event.relatedTarget)) {
$el._tooltip.$tooltip.addEventListener(
'mouseleave',
({ relatedTarget }) => {
if (!relatedTarget || !$el.contains(relatedTarget)) {
'pointerleave',
(event) => {
if (event.pointerType !== 'mouse') {
return;
}
if (!event.relatedTarget || !$el.contains(event.relatedTarget)) {
$el._tooltip.hide();
}
},
@@ -421,6 +447,9 @@ export const createTooltip = ($el, content, options) => {
};
$el._tooltip.focusListener = () => {
if (document.hidden) {
return;
}
$el._tooltip.show();
};
@@ -432,11 +461,11 @@ export const createTooltip = ($el, content, options) => {
for (const trigger of options.trigger.split(' ')) {
switch (trigger) {
case 'mouseenter': {
$el.addEventListener('mouseenter', $el._tooltip.mouseEnterListener);
listeners.push({ el: $el, event: 'mouseenter', listener: $el._tooltip.mouseEnterListener });
$el.addEventListener('pointerenter', $el._tooltip.mouseEnterListener);
listeners.push({ el: $el, event: 'pointerenter', listener: $el._tooltip.mouseEnterListener });
$el.addEventListener('mouseleave', $el._tooltip.mouseLeaveListener);
listeners.push({ el: $el, event: 'mouseleave', listener: $el._tooltip.mouseLeaveListener });
$el.addEventListener('pointerleave', $el._tooltip.mouseLeaveListener);
listeners.push({ el: $el, event: 'pointerleave', listener: $el._tooltip.mouseLeaveListener });
break;
}
case 'click': {
@@ -444,8 +473,8 @@ export const createTooltip = ($el, content, options) => {
listeners.push({ el: $el, event: 'click', listener: $el._tooltip.clickListener });
if (!options.interactive) {
$el.addEventListener('mouseleave', $el._tooltip.mouseLeaveListener);
listeners.push({ el: $el, event: 'mouseleave', listener: $el._tooltip.mouseLeaveListener });
$el.addEventListener('pointerleave', $el._tooltip.mouseLeaveListener);
listeners.push({ el: $el, event: 'pointerleave', listener: $el._tooltip.mouseLeaveListener });
}
break;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@advdominion/tooltip",
"version": "5.0.0",
"version": "6.0.0",
"type": "module",
"packageManager": "yarn@4.9.4",
"main": "index.js",