v4.0.0
This commit is contained in:
		@@ -1,3 +1,11 @@
 | 
			
		||||
## v4.0.0
 | 
			
		||||
 | 
			
		||||
- Переработана логика инициализации и обновления тултипа
 | 
			
		||||
- Добавлены новые триггеры: `focus`, `blur`
 | 
			
		||||
- Опция `hideOnClick` теперь поддерживает значения: `true`, `'all'`, `'toggle'`
 | 
			
		||||
- Исправлены ошибки с позиционированием, анимацией и стилями
 | 
			
		||||
- Оптимизировано управление событиями и очистка ресурсов
 | 
			
		||||
 | 
			
		||||
## v3.0.1
 | 
			
		||||
 | 
			
		||||
- Исправлена работа событий
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							@@ -22,7 +22,7 @@ import { createTooltip } from '@advdominion/tooltip';
 | 
			
		||||
createTooltip(document.querySelector('button'), 'Подсказка');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Все настройки со значениями по-умолчанию
 | 
			
		||||
#### Все настройки со значениями по умолчанию
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { createTooltip } from '@advdominion/tooltip';
 | 
			
		||||
@@ -46,7 +46,7 @@ createTooltip(document.querySelector('button'), 'Подсказка', {
 | 
			
		||||
    trigger: 'mouseenter',
 | 
			
		||||
    virtualReference: undefined,
 | 
			
		||||
    zIndex: '',
 | 
			
		||||
    // Callback-функции, по-умолчанию не заданы
 | 
			
		||||
    // Callback-функции, по умолчанию не заданы
 | 
			
		||||
    onCreate(instance) {},
 | 
			
		||||
    onMount(instance) {},
 | 
			
		||||
    onShow(instance) {},
 | 
			
		||||
@@ -56,6 +56,12 @@ createTooltip(document.querySelector('button'), 'Подсказка', {
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### hideOnClick
 | 
			
		||||
 | 
			
		||||
- `true` (по умолчанию) — всплывающая подсказка скрывается при клике по любому элементу на странице (**кроме** самой всплывающей подсказки).
 | 
			
		||||
- `'all'` — всплывающая подсказка скрывается при клике по любому элементу на странице (**включая** саму всплывающую подсказку).
 | 
			
		||||
- `'toggle'` — всплывающая подсказка скрывается только при клике по элементу, который её вызывает.
 | 
			
		||||
 | 
			
		||||
##### virtualReference
 | 
			
		||||
 | 
			
		||||
Настройка используется для кастомного позиционирования, ожидает объект с методом `getBoundingClientRect`.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										385
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										385
									
								
								index.js
									
									
									
									
									
								
							@@ -19,7 +19,7 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        delay: [0, 0],
 | 
			
		||||
        duration: [0, 0],
 | 
			
		||||
        easing: ['linear', 'linear'],
 | 
			
		||||
        hideOnClick: true, // Возможные значения: true, 'all', 'trigger'
 | 
			
		||||
        hideOnClick: true, // Возможные значения: true, 'all', 'toggle'
 | 
			
		||||
        interactive: true,
 | 
			
		||||
        offset: [0, 8],
 | 
			
		||||
        placement: 'top',
 | 
			
		||||
@@ -31,61 +31,52 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        ...options,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const setOptionFromDataAttribute = (attribute) => {
 | 
			
		||||
        if ($el.dataset[attribute] !== undefined) {
 | 
			
		||||
            let value = $el.dataset[attribute];
 | 
			
		||||
    for (const [key, value] of Object.entries($el.dataset)) {
 | 
			
		||||
        if (key.startsWith('tooltip')) {
 | 
			
		||||
            let parsedValue = value;
 | 
			
		||||
            try {
 | 
			
		||||
                value = JSON.parse($el.dataset[attribute]);
 | 
			
		||||
            } catch {}
 | 
			
		||||
            options[attributeToOption(attribute)] = value;
 | 
			
		||||
                parsedValue = JSON.parse(value);
 | 
			
		||||
            } catch {} // eslint-disable-line no-empty
 | 
			
		||||
            options[attributeToOption(key)] = parsedValue;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    setOptionFromDataAttribute('tooltipAnimation');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipAppendTo');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipArrow');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipDelay');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipDuration');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipEasing');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipHideOnClick');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipInteractive');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipOffset');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipPlacement');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipShiftPadding');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipTheme');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipTrigger');
 | 
			
		||||
    setOptionFromDataAttribute('tooltipZIndex');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let showTimeout;
 | 
			
		||||
    let hideTimeout;
 | 
			
		||||
 | 
			
		||||
    let autoUpdateCleanup = new Function();
 | 
			
		||||
    let rafId;
 | 
			
		||||
    const listeners = [];
 | 
			
		||||
 | 
			
		||||
    $el._tooltip = {
 | 
			
		||||
        options,
 | 
			
		||||
        isVisible: false,
 | 
			
		||||
        $tooltip: undefined,
 | 
			
		||||
        $container: undefined,
 | 
			
		||||
        $arrow: undefined,
 | 
			
		||||
        $interactive: undefined,
 | 
			
		||||
        autoUpdateCleanup: () => {},
 | 
			
		||||
 | 
			
		||||
        setContent(updatedContent) {
 | 
			
		||||
            if (updatedContent !== undefined) {
 | 
			
		||||
                content = updatedContent;
 | 
			
		||||
            }
 | 
			
		||||
            if ($el._tooltip.$tooltip) {
 | 
			
		||||
                const $container = $el._tooltip.$tooltip.querySelector('.tooltip__container');
 | 
			
		||||
            if ($el._tooltip.$container) {
 | 
			
		||||
                if (content instanceof HTMLElement) {
 | 
			
		||||
                    $container.innerHTML = '';
 | 
			
		||||
                    $container.append(content);
 | 
			
		||||
                    $el._tooltip.$container.innerHTML = '';
 | 
			
		||||
                    $el._tooltip.$container.append(content);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $container.innerHTML = content;
 | 
			
		||||
                    $el._tooltip.$container.innerHTML = content;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        async updateOptions(updatedOptions = {}) {
 | 
			
		||||
            for (const [name, value] of Object.entries(updatedOptions)) {
 | 
			
		||||
                options[name] = value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (updatedOptions.arrow !== undefined && $el._tooltip.$tooltip) {
 | 
			
		||||
                if (options.arrow) {
 | 
			
		||||
                    if (!$el._tooltip.$tooltip.querySelector('.tooltip__arrow')) {
 | 
			
		||||
                    if (!$el._tooltip.$arrow) {
 | 
			
		||||
                        $el._tooltip.$tooltip.insertAdjacentHTML(
 | 
			
		||||
                            'afterbegin',
 | 
			
		||||
                            `
 | 
			
		||||
@@ -95,56 +86,82 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
                                </div>
 | 
			
		||||
                            `,
 | 
			
		||||
                        );
 | 
			
		||||
                        $el._tooltip.$arrow = $el._tooltip.$tooltip.querySelector('.tooltip__arrow');
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    $el._tooltip.$tooltip.querySelector('.tooltip__arrow')?.remove();
 | 
			
		||||
                    $el._tooltip.$arrow?.remove();
 | 
			
		||||
                    $el._tooltip.$arrow = undefined;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (updatedOptions.interactive !== undefined) {
 | 
			
		||||
                for (const { el, event, listener } of listeners) {
 | 
			
		||||
                    el.removeEventListener(event, listener);
 | 
			
		||||
                }
 | 
			
		||||
                listeners.length = 0;
 | 
			
		||||
                registerListeners();
 | 
			
		||||
                if ($el._tooltip.$tooltip) {
 | 
			
		||||
                    if (options.interactive) {
 | 
			
		||||
                        if (!$el._tooltip.$tooltip.querySelector('.tooltip__interactive-helper')) {
 | 
			
		||||
                        if (!$el._tooltip.$interactive) {
 | 
			
		||||
                            $el._tooltip.$tooltip.insertAdjacentHTML(
 | 
			
		||||
                                'afterbegin',
 | 
			
		||||
                                `
 | 
			
		||||
                                    <div
 | 
			
		||||
                                        class="tooltip__interactive-helper"
 | 
			
		||||
                                        style="position: absolute; z-index; -1;">
 | 
			
		||||
                                        style="position: absolute; z-index: -1;">
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                `,
 | 
			
		||||
                            );
 | 
			
		||||
                            $el._tooltip.$interactive =
 | 
			
		||||
                                $el._tooltip.$tooltip.querySelector('.tooltip__interactive-helper');
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $el._tooltip.$tooltip.querySelector('.tooltip__interactive-helper')?.remove();
 | 
			
		||||
                        $el._tooltip.$interactive?.remove();
 | 
			
		||||
                        $el._tooltip.$interactive = undefined;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (updatedOptions.theme !== undefined && $el._tooltip.$tooltip) {
 | 
			
		||||
                const classIndex = [...$el._tooltip.$tooltip.classList].findIndex((className) =>
 | 
			
		||||
                    className.startsWith('tooltip_theme_'),
 | 
			
		||||
                );
 | 
			
		||||
                $el._tooltip.$tooltip.classList.replace(
 | 
			
		||||
                    $el._tooltip.$tooltip.classList[classIndex],
 | 
			
		||||
                    `tooltip_theme_${options.theme}`,
 | 
			
		||||
                );
 | 
			
		||||
                if (classIndex === -1) {
 | 
			
		||||
                    $el._tooltip.$tooltip.classList.add(`tooltip_theme_${options.theme}`);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $el._tooltip.$tooltip.classList.replace(
 | 
			
		||||
                        $el._tooltip.$tooltip.classList[classIndex],
 | 
			
		||||
                        `tooltip_theme_${options.theme}`,
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (updatedOptions.zIndex !== undefined && $el._tooltip.$tooltip) {
 | 
			
		||||
                Object.assign($el._tooltip.$tooltip.style, { zIndex: options.zIndex });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($el._tooltip.$tooltip) {
 | 
			
		||||
                await $el._tooltip.updatePosition();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        destroy() {
 | 
			
		||||
            if (!$el._tooltip) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.$tooltip?.remove();
 | 
			
		||||
            autoUpdateCleanup();
 | 
			
		||||
 | 
			
		||||
            // Вызываем autoUpdateCleanup только если всплывающая подсказка была видна (иначе вызывать её не имеет смысла)
 | 
			
		||||
            if ($el._tooltip.isVisible) {
 | 
			
		||||
                $el._tooltip.autoUpdateCleanup();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (const { el, event, listener } of listeners) {
 | 
			
		||||
                el.removeEventListener(event, listener);
 | 
			
		||||
            }
 | 
			
		||||
            listeners.length = 0;
 | 
			
		||||
 | 
			
		||||
            delete $el._tooltip;
 | 
			
		||||
        },
 | 
			
		||||
    };
 | 
			
		||||
@@ -153,9 +170,7 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        options.onCreate($el._tooltip);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.show = async (params = {}) => {
 | 
			
		||||
        const { immediately } = params;
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.show = async ({ immediately } = {}) => {
 | 
			
		||||
        clearTimeout(hideTimeout);
 | 
			
		||||
 | 
			
		||||
        if (!$el._tooltip.$tooltip) {
 | 
			
		||||
@@ -163,87 +178,9 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.$tooltip = document.createElement('div');
 | 
			
		||||
            $el._tooltip.$tooltip._reference = $el;
 | 
			
		||||
            $el._tooltip.updatePosition = async () => {
 | 
			
		||||
                const $arrow = $el._tooltip.$tooltip.querySelector('.tooltip__arrow');
 | 
			
		||||
 | 
			
		||||
                const { x, y, placement, middlewareData } = await computePosition(
 | 
			
		||||
                    options.virtualReference ?? $el,
 | 
			
		||||
                    $el._tooltip.$tooltip,
 | 
			
		||||
                    {
 | 
			
		||||
                        placement: options.placement,
 | 
			
		||||
                        middleware: [
 | 
			
		||||
                            offset({
 | 
			
		||||
                                mainAxis: options.offset[1],
 | 
			
		||||
                                crossAxis: options.offset[0],
 | 
			
		||||
                            }),
 | 
			
		||||
                            flip(),
 | 
			
		||||
                            shift({
 | 
			
		||||
                                padding: {
 | 
			
		||||
                                    top: options.shiftPadding[1],
 | 
			
		||||
                                    right: options.shiftPadding[0],
 | 
			
		||||
                                    bottom: options.shiftPadding[1],
 | 
			
		||||
                                    left: options.shiftPadding[0],
 | 
			
		||||
                                },
 | 
			
		||||
                            }),
 | 
			
		||||
                            arrow({
 | 
			
		||||
                                element: $arrow,
 | 
			
		||||
                                padding: Number.parseInt(
 | 
			
		||||
                                    getComputedStyle($el._tooltip.$tooltip.querySelector('.tooltip__container'))[
 | 
			
		||||
                                        'border-radius'
 | 
			
		||||
                                    ],
 | 
			
		||||
                                ),
 | 
			
		||||
                            }),
 | 
			
		||||
                        ],
 | 
			
		||||
                    },
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                Object.assign($el._tooltip.$tooltip.style, {
 | 
			
		||||
                    transform: `translate(${roundByDPR(x)}px, ${roundByDPR(y)}px)`,
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                const side = placement.split('-')[0];
 | 
			
		||||
                const staticSide = {
 | 
			
		||||
                    top: 'bottom',
 | 
			
		||||
                    right: 'left',
 | 
			
		||||
                    bottom: 'top',
 | 
			
		||||
                    left: 'right',
 | 
			
		||||
                }[side];
 | 
			
		||||
 | 
			
		||||
                $el._tooltip.$tooltip.classList.remove(
 | 
			
		||||
                    'tooltip_side_top',
 | 
			
		||||
                    'tooltip_side_bottom',
 | 
			
		||||
                    'tooltip_side_left',
 | 
			
		||||
                    'tooltip_side_right',
 | 
			
		||||
                );
 | 
			
		||||
                $el._tooltip.$tooltip.classList.add(`tooltip_side_${side}`);
 | 
			
		||||
 | 
			
		||||
                const $interactive = $el._tooltip.$tooltip.querySelector('.tooltip__interactive-helper');
 | 
			
		||||
                if ($interactive) {
 | 
			
		||||
                    Object.assign($interactive.style, {
 | 
			
		||||
                        width: side === 'left' || side === 'right' ? `${options.offset[1]}px` : '100%',
 | 
			
		||||
                        height: side === 'top' || side === 'bottom' ? `${options.offset[1]}px` : '100%',
 | 
			
		||||
                        top: '',
 | 
			
		||||
                        bottom: '',
 | 
			
		||||
                        left: '',
 | 
			
		||||
                        right: '',
 | 
			
		||||
                        [staticSide]: `-${options.offset[1]}px`,
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if ($arrow && middlewareData.arrow) {
 | 
			
		||||
                    const { x, y } = middlewareData.arrow;
 | 
			
		||||
                    Object.assign($arrow.style, {
 | 
			
		||||
                        left: x === undefined ? '' : `${x}px`,
 | 
			
		||||
                        top: y === undefined ? '' : `${y}px`,
 | 
			
		||||
                        right: '',
 | 
			
		||||
                        bottom: '',
 | 
			
		||||
                        [staticSide]: `-${$arrow.offsetWidth / 2}px`,
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.$tooltip.classList.add('tooltip', `tooltip_theme_${options.theme}`);
 | 
			
		||||
            Object.assign($el._tooltip.$tooltip.style, { zIndex: options.zIndex });
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.$tooltip.innerHTML = `
 | 
			
		||||
                <div class="tooltip__root">
 | 
			
		||||
                    ${
 | 
			
		||||
@@ -251,7 +188,7 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
                            ? `
 | 
			
		||||
                                <div
 | 
			
		||||
                                    class="tooltip__interactive-helper"
 | 
			
		||||
                                    style="position: absolute; z-index; -1;">
 | 
			
		||||
                                    style="position: absolute; z-index: -1;">
 | 
			
		||||
                                </div>
 | 
			
		||||
                            `
 | 
			
		||||
                            : ''
 | 
			
		||||
@@ -269,8 +206,71 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
                    <div class="tooltip__container"></div>
 | 
			
		||||
                </div>
 | 
			
		||||
            `;
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.$container = $el._tooltip.$tooltip.querySelector('.tooltip__container');
 | 
			
		||||
            $el._tooltip.$arrow = $el._tooltip.$tooltip.querySelector('.tooltip__arrow');
 | 
			
		||||
            $el._tooltip.$interactive = $el._tooltip.$tooltip.querySelector('.tooltip__interactive-helper');
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.setContent();
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.updatePosition = () => {
 | 
			
		||||
                cancelAnimationFrame(rafId);
 | 
			
		||||
                rafId = requestAnimationFrame(async () => {
 | 
			
		||||
                    const { x, y, placement, middlewareData } = await computePosition(
 | 
			
		||||
                        options.virtualReference ?? $el,
 | 
			
		||||
                        $el._tooltip.$tooltip,
 | 
			
		||||
                        {
 | 
			
		||||
                            placement: options.placement,
 | 
			
		||||
                            middleware: [
 | 
			
		||||
                                offset({ mainAxis: options.offset[1], crossAxis: options.offset[0] }),
 | 
			
		||||
                                flip(),
 | 
			
		||||
                                shift({
 | 
			
		||||
                                    padding: {
 | 
			
		||||
                                        top: options.shiftPadding[1],
 | 
			
		||||
                                        right: options.shiftPadding[0],
 | 
			
		||||
                                        bottom: options.shiftPadding[1],
 | 
			
		||||
                                        left: options.shiftPadding[0],
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                                arrow({ element: $el._tooltip.$arrow }),
 | 
			
		||||
                            ],
 | 
			
		||||
                        },
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    Object.assign($el._tooltip.$tooltip.style, {
 | 
			
		||||
                        transform: `translate(${roundByDPR(x)}px, ${roundByDPR(y)}px)`,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    const side = placement.split('-')[0];
 | 
			
		||||
                    const staticSide = { top: 'bottom', right: 'left', bottom: 'top', left: 'right' }[side];
 | 
			
		||||
 | 
			
		||||
                    $el._tooltip.$tooltip.classList.remove(
 | 
			
		||||
                        'tooltip_side_top',
 | 
			
		||||
                        'tooltip_side_bottom',
 | 
			
		||||
                        'tooltip_side_left',
 | 
			
		||||
                        'tooltip_side_right',
 | 
			
		||||
                    );
 | 
			
		||||
                    $el._tooltip.$tooltip.classList.add(`tooltip_side_${side}`);
 | 
			
		||||
 | 
			
		||||
                    if ($el._tooltip.$interactive) {
 | 
			
		||||
                        Object.assign($el._tooltip.$interactive.style, {
 | 
			
		||||
                            width: side === 'left' || side === 'right' ? `${options.offset[1]}px` : '100%',
 | 
			
		||||
                            height: side === 'top' || side === 'bottom' ? `${options.offset[1]}px` : '100%',
 | 
			
		||||
                            [staticSide]: `-${options.offset[1]}px`,
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if ($el._tooltip.$arrow && middlewareData.arrow) {
 | 
			
		||||
                        const { x, y } = middlewareData.arrow;
 | 
			
		||||
                        Object.assign($el._tooltip.$arrow.style, {
 | 
			
		||||
                            left: x === undefined ? '' : `${x}px`,
 | 
			
		||||
                            top: y === undefined ? '' : `${y}px`,
 | 
			
		||||
                            [staticSide]: `-${$el._tooltip.$arrow.offsetWidth / 2}px`,
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if (options.onMount) {
 | 
			
		||||
                options.onMount($el._tooltip);
 | 
			
		||||
            }
 | 
			
		||||
@@ -281,13 +281,15 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        showTimeout = setTimeout(
 | 
			
		||||
            async () => {
 | 
			
		||||
                if (!$el._tooltip.isVisible) {
 | 
			
		||||
                    if (options.appendTo === 'parent') {
 | 
			
		||||
                        $el.parentElement.append($el._tooltip.$tooltip);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        options.appendTo.append($el._tooltip.$tooltip);
 | 
			
		||||
                    }
 | 
			
		||||
                    (options.appendTo === 'parent' ? $el.parentElement : options.appendTo).append(
 | 
			
		||||
                        $el._tooltip.$tooltip,
 | 
			
		||||
                    );
 | 
			
		||||
                    $el._tooltip.isVisible = true;
 | 
			
		||||
                    autoUpdateCleanup = autoUpdate($el, $el._tooltip.$tooltip, $el._tooltip.updatePosition);
 | 
			
		||||
                    $el._tooltip.autoUpdateCleanup = autoUpdate(
 | 
			
		||||
                        $el,
 | 
			
		||||
                        $el._tooltip.$tooltip,
 | 
			
		||||
                        $el._tooltip.updatePosition,
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    if (
 | 
			
		||||
                        options.hideOnClick &&
 | 
			
		||||
@@ -305,10 +307,12 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
                        options.onShow($el._tooltip);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    await $el._tooltip.$tooltip.querySelector('.tooltip__root').animate(options.animation[0], {
 | 
			
		||||
                        duration: immediately ? 0 : options.duration[0],
 | 
			
		||||
                        easing: options.easing[0],
 | 
			
		||||
                    }).finished;
 | 
			
		||||
                    try {
 | 
			
		||||
                        await $el._tooltip.$tooltip.querySelector('.tooltip__root').animate(options.animation[0], {
 | 
			
		||||
                            duration: immediately ? 0 : options.duration[0],
 | 
			
		||||
                            easing: options.easing[0],
 | 
			
		||||
                        }).finished;
 | 
			
		||||
                    } catch {} // eslint-disable-line no-empty
 | 
			
		||||
 | 
			
		||||
                    if (options.onShown) {
 | 
			
		||||
                        options.onShown($el._tooltip);
 | 
			
		||||
@@ -319,11 +323,8 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.hide = (params = {}) => {
 | 
			
		||||
        const { immediately } = params;
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.hide = ({ immediately } = {}) => {
 | 
			
		||||
        clearTimeout(showTimeout);
 | 
			
		||||
 | 
			
		||||
        hideTimeout = setTimeout(
 | 
			
		||||
            async () => {
 | 
			
		||||
                if ($el._tooltip.isVisible) {
 | 
			
		||||
@@ -331,14 +332,18 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
                        options.onHide($el._tooltip);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    await $el._tooltip.$tooltip.querySelector('.tooltip__root').animate(options.animation[1], {
 | 
			
		||||
                        duration: immediately ? 0 : options.duration[1],
 | 
			
		||||
                        easing: options.easing[1],
 | 
			
		||||
                    }).finished;
 | 
			
		||||
                    try {
 | 
			
		||||
                        await $el._tooltip.$tooltip.querySelector('.tooltip__root').animate(options.animation[1], {
 | 
			
		||||
                            duration: immediately ? 0 : options.duration[1],
 | 
			
		||||
                            easing: options.easing[1],
 | 
			
		||||
                        }).finished;
 | 
			
		||||
                    } catch {} // eslint-disable-line no-empty
 | 
			
		||||
 | 
			
		||||
                    $el._tooltip.$tooltip.remove();
 | 
			
		||||
                    if ($el._tooltip.$tooltip) {
 | 
			
		||||
                        $el._tooltip.$tooltip.remove();
 | 
			
		||||
                    }
 | 
			
		||||
                    $el._tooltip.isVisible = false;
 | 
			
		||||
                    autoUpdateCleanup();
 | 
			
		||||
                    $el._tooltip.autoUpdateCleanup();
 | 
			
		||||
 | 
			
		||||
                    if (options.onHidden) {
 | 
			
		||||
                        options.onHidden($el._tooltip);
 | 
			
		||||
@@ -350,14 +355,24 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.hideOnClickListener = ({ target }) => {
 | 
			
		||||
        if (
 | 
			
		||||
            $el._tooltip.isVisible &&
 | 
			
		||||
            (options.hideOnClick === 'all' ||
 | 
			
		||||
                $el.contains(target) ||
 | 
			
		||||
                (options.hideOnClick !== 'toggle' && !$el._tooltip.$tooltip.contains(target)))
 | 
			
		||||
        ) {
 | 
			
		||||
            document.body.removeEventListener('click', $el._tooltip.hideOnClickListener);
 | 
			
		||||
        if (!$el._tooltip.isVisible) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (options.hideOnClick === 'all') {
 | 
			
		||||
            $el._tooltip.hide();
 | 
			
		||||
            document.body.removeEventListener('click', $el._tooltip.hideOnClickListener);
 | 
			
		||||
        } else if (options.hideOnClick === 'toggle') {
 | 
			
		||||
            if ($el.contains(target)) {
 | 
			
		||||
                $el._tooltip.hide();
 | 
			
		||||
                document.body.removeEventListener('click', $el._tooltip.hideOnClickListener);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // options.hideOnClick === true
 | 
			
		||||
            if ($el.contains(target) || !$el._tooltip.$tooltip.contains(target)) {
 | 
			
		||||
                $el._tooltip.hide();
 | 
			
		||||
                document.body.removeEventListener('click', $el._tooltip.hideOnClickListener);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -372,64 +387,58 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.mouseLeaveListener = ({ relatedTarget }) => {
 | 
			
		||||
        if (options.interactive) {
 | 
			
		||||
            if ($el._tooltip.$tooltip.contains(relatedTarget)) {
 | 
			
		||||
                $el._tooltip.$tooltip.addEventListener(
 | 
			
		||||
                    'mouseleave',
 | 
			
		||||
                    ({ relatedTarget }) => {
 | 
			
		||||
                        if (!$el.contains(relatedTarget)) {
 | 
			
		||||
                            $el._tooltip.hide();
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        once: true,
 | 
			
		||||
                    },
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                $el._tooltip.hide();
 | 
			
		||||
            }
 | 
			
		||||
        if (options.interactive && relatedTarget && $el._tooltip.$tooltip?.contains(relatedTarget)) {
 | 
			
		||||
            $el._tooltip.$tooltip.addEventListener(
 | 
			
		||||
                'mouseleave',
 | 
			
		||||
                ({ relatedTarget }) => {
 | 
			
		||||
                    if (!relatedTarget || !$el.contains(relatedTarget)) {
 | 
			
		||||
                        $el._tooltip.hide();
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                { once: true },
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            $el._tooltip.hide();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.focusListener = () => {
 | 
			
		||||
        $el._tooltip.show();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.blurListener = () => {
 | 
			
		||||
        $el._tooltip.hide();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const registerListeners = () => {
 | 
			
		||||
        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,
 | 
			
		||||
                    });
 | 
			
		||||
                    listeners.push({ el: $el, event: 'mouseenter', listener: $el._tooltip.mouseEnterListener });
 | 
			
		||||
 | 
			
		||||
                    $el.addEventListener('mouseleave', $el._tooltip.mouseLeaveListener);
 | 
			
		||||
                    listeners.push({
 | 
			
		||||
                        el: $el,
 | 
			
		||||
                        event: 'mouseleave',
 | 
			
		||||
                        listener: $el._tooltip.mouseLeaveListener,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    listeners.push({ el: $el, event: 'mouseleave', listener: $el._tooltip.mouseLeaveListener });
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case 'click': {
 | 
			
		||||
                    $el.addEventListener('click', $el._tooltip.clickListener);
 | 
			
		||||
                    listeners.push({
 | 
			
		||||
                        el: $el,
 | 
			
		||||
                        event: 'click',
 | 
			
		||||
                        listener: $el._tooltip.clickListener,
 | 
			
		||||
                    });
 | 
			
		||||
                    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,
 | 
			
		||||
                        });
 | 
			
		||||
                        listeners.push({ el: $el, event: 'mouseleave', listener: $el._tooltip.mouseLeaveListener });
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case 'focus': {
 | 
			
		||||
                    $el.addEventListener('focus', $el._tooltip.focusListener);
 | 
			
		||||
                    listeners.push({ el: $el, event: 'focus', listener: $el._tooltip.focusListener });
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case 'blur': {
 | 
			
		||||
                    $el.addEventListener('blur', $el._tooltip.blurListener);
 | 
			
		||||
                    listeners.push({ el: $el, event: 'blur', listener: $el._tooltip.blurListener });
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user