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