v2.0.0
This commit is contained in:
		
							
								
								
									
										12
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
## v2.0.0
 | 
			
		||||
 | 
			
		||||
-   К `_tooltip.$tooltip` добавлено свойство `_reference` для доступа к элементу, на котором был вызван `createTooltip`
 | 
			
		||||
-   Для функций `show/hide` добавлен параметр `immediately` для мнгновенного открытия/закрытия всплывающей подсказки (`_tooltip.hide({ immediately: true })`)
 | 
			
		||||
-   Добавлена опция `shiftPadding` для добавления отступов от краёв области видимости по осям x/y
 | 
			
		||||
-   Добавлена опция `animation` для кастомизации анимации при открытии/закрытии всплывающей подсказки (для этого всё внутри `.tooltip` было обёрнуто в `.tooltip__root` и анимация применяется именно к этому блоку)
 | 
			
		||||
-   Опция `_tooltip._options` переименована в `_tooltip.options`
 | 
			
		||||
-   Оптимизция кода, исправление ошибок
 | 
			
		||||
-   Доработки по README.md
 | 
			
		||||
-   Доработки по .npmignore
 | 
			
		||||
 | 
			
		||||
## v1.0.0
 | 
			
		||||
							
								
								
									
										40
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								README.md
									
									
									
									
									
								
							@@ -28,6 +28,10 @@ createTooltip(document.querySelector('button'), 'Подсказка');
 | 
			
		||||
import { createTooltip } from '@advdominion/tooltip';
 | 
			
		||||
 | 
			
		||||
createTooltip(document.querySelector('button'), 'Подсказка', {
 | 
			
		||||
    animation: [
 | 
			
		||||
        [{ opacity: 0 }, { opacity: 1 }],
 | 
			
		||||
        [{ opacity: 1 }, { opacity: 0 }],
 | 
			
		||||
    ],
 | 
			
		||||
    appendTo: document.body,
 | 
			
		||||
    arrow: true,
 | 
			
		||||
    delay: [0, 0],
 | 
			
		||||
@@ -37,6 +41,7 @@ createTooltip(document.querySelector('button'), 'Подсказка', {
 | 
			
		||||
    interactive: true,
 | 
			
		||||
    offset: [0, 8],
 | 
			
		||||
    placement: 'top',
 | 
			
		||||
    shiftPadding: [8, 0],
 | 
			
		||||
    theme: 'light',
 | 
			
		||||
    trigger: 'mouseenter',
 | 
			
		||||
    virtialReference: undefined,
 | 
			
		||||
@@ -76,8 +81,34 @@ createTooltip(document.querySelector('button'), 'Подсказка', {
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Свойства
 | 
			
		||||
 | 
			
		||||
#### $tooltip
 | 
			
		||||
 | 
			
		||||
DOM-элемент всплывающей подсказки (имеет свойство `_reference` для доступа к элементу, на котором был вызван `createTooltip`)
 | 
			
		||||
 | 
			
		||||
#### options
 | 
			
		||||
 | 
			
		||||
Текущие настройки
 | 
			
		||||
 | 
			
		||||
#### isVisible
 | 
			
		||||
 | 
			
		||||
Видимость всплывающей подсказки - `true`/`false`
 | 
			
		||||
 | 
			
		||||
#### Методы
 | 
			
		||||
 | 
			
		||||
##### show
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
document.querySelector('button')._tooltip.show();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
##### hide
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
document.querySelector('button')._tooltip.hide();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
##### setContent
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
@@ -96,6 +127,12 @@ document.querySelector('button')._tooltip.updateOptions({ placement: 'bottom' })
 | 
			
		||||
<button type="button" data-tooltip-placement="bottom">Кнопка</button>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
##### destroy
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
document.querySelector('button')._tooltip.destroy();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Стили
 | 
			
		||||
 | 
			
		||||
```scss
 | 
			
		||||
@@ -113,6 +150,9 @@ $b: '.tooltip';
 | 
			
		||||
        max-width: 300px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__root {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__arrow {
 | 
			
		||||
        #{$b}_theme_light & {
 | 
			
		||||
            background-color: white;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										215
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										215
									
								
								index.js
									
									
									
									
									
								
							@@ -3,17 +3,27 @@ const roundByDPR = (value) => {
 | 
			
		||||
    return Math.round(value * dpr) / dpr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const attributeToOption = (attribute) => {
 | 
			
		||||
    attribute = attribute.replace('tooltip', '');
 | 
			
		||||
    return attribute.charAt(0).toLowerCase() + attribute.slice(1);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const createTooltip = ($el, content, options) => {
 | 
			
		||||
    options = {
 | 
			
		||||
        animation: [
 | 
			
		||||
            [{ opacity: 0 }, { opacity: 1 }],
 | 
			
		||||
            [{ opacity: 1 }, { opacity: 0 }],
 | 
			
		||||
        ],
 | 
			
		||||
        appendTo: document.body,
 | 
			
		||||
        arrow: true,
 | 
			
		||||
        delay: [0, 0],
 | 
			
		||||
        duration: [0, 0],
 | 
			
		||||
        easing: ['linear', 'linear'],
 | 
			
		||||
        hideOnClick: true,
 | 
			
		||||
        hideOnClick: true, // Возможные значения: true, 'all', 'trigger'
 | 
			
		||||
        interactive: true,
 | 
			
		||||
        offset: [0, 8],
 | 
			
		||||
        placement: 'top',
 | 
			
		||||
        shiftPadding: [8, 0],
 | 
			
		||||
        theme: 'light',
 | 
			
		||||
        trigger: 'mouseenter',
 | 
			
		||||
        virtialReference: undefined,
 | 
			
		||||
@@ -21,46 +31,29 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        ...options,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipArrow !== undefined) {
 | 
			
		||||
        options.arrow = $el.dataset.tooltipArrow === 'true';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipHideOnClick !== undefined) {
 | 
			
		||||
        switch ($el.dataset.tooltipHideOnClick) {
 | 
			
		||||
            case 'all':
 | 
			
		||||
            case 'toggle': {
 | 
			
		||||
                options.hideOnClick = $el.dataset.tooltipHideOnClick;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                options.hideOnClick = $el.dataset.tooltipHideOnClick === 'true';
 | 
			
		||||
            }
 | 
			
		||||
    const setOptionFromDataAttribute = (attribute) => {
 | 
			
		||||
        if ($el.dataset[attribute] !== undefined) {
 | 
			
		||||
            let value = $el.dataset[attribute];
 | 
			
		||||
            try {
 | 
			
		||||
                value = JSON.parse($el.dataset[attribute]);
 | 
			
		||||
            } catch {}
 | 
			
		||||
            options[attributeToOption(attribute)] = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipInteractive !== undefined) {
 | 
			
		||||
        options.interactive = $el.dataset.tooltipInteractive === 'true';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipOffset !== undefined) {
 | 
			
		||||
        options.offset = JSON.parse($el.dataset.tooltipOffset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipPlacement !== undefined) {
 | 
			
		||||
        options.placement = $el.dataset.tooltipPlacement;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipTheme !== undefined) {
 | 
			
		||||
        options.theme = $el.dataset.tooltipTheme;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipTrigger !== undefined) {
 | 
			
		||||
        options.trigger = $el.dataset.tooltipTrigger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ($el.dataset.tooltipZIndex !== undefined) {
 | 
			
		||||
        options.zIndex = $el.dataset.tooltipZIndex;
 | 
			
		||||
    }
 | 
			
		||||
    setOptionFromDataAttribute('tooltipAnimation');
 | 
			
		||||
    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;
 | 
			
		||||
@@ -69,7 +62,7 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
    const listeners = [];
 | 
			
		||||
 | 
			
		||||
    $el._tooltip = {
 | 
			
		||||
        _options: options,
 | 
			
		||||
        options,
 | 
			
		||||
        isVisible: false,
 | 
			
		||||
        setContent(updatedContent) {
 | 
			
		||||
            if (updatedContent !== undefined) {
 | 
			
		||||
@@ -159,13 +152,16 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
        options.onCreate($el._tooltip);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.show = async () => {
 | 
			
		||||
    $el._tooltip.show = async (params = {}) => {
 | 
			
		||||
        const { immediately } = params;
 | 
			
		||||
 | 
			
		||||
        clearTimeout(hideTimeout);
 | 
			
		||||
 | 
			
		||||
        if (!$el._tooltip.$tooltip) {
 | 
			
		||||
            const { computePosition, offset, flip, shift, arrow } = await import('@floating-ui/dom');
 | 
			
		||||
 | 
			
		||||
            $el._tooltip.$tooltip = document.createElement('div');
 | 
			
		||||
            $el._tooltip.$tooltip._reference = $el;
 | 
			
		||||
            $el._tooltip.updatePosition = async () => {
 | 
			
		||||
                const $arrow = $el._tooltip.$tooltip.querySelector('.tooltip__arrow');
 | 
			
		||||
 | 
			
		||||
@@ -180,7 +176,14 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
                                crossAxis: options.offset[0],
 | 
			
		||||
                            }),
 | 
			
		||||
                            flip(),
 | 
			
		||||
                            shift(),
 | 
			
		||||
                            shift({
 | 
			
		||||
                                padding: {
 | 
			
		||||
                                    top: options.shiftPadding[1],
 | 
			
		||||
                                    right: options.shiftPadding[0],
 | 
			
		||||
                                    bottom: options.shiftPadding[1],
 | 
			
		||||
                                    left: options.shiftPadding[0],
 | 
			
		||||
                                },
 | 
			
		||||
                            }),
 | 
			
		||||
                            arrow({
 | 
			
		||||
                                element: $arrow,
 | 
			
		||||
                                padding: Number.parseInt(
 | 
			
		||||
@@ -241,27 +244,29 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
            $el._tooltip.$tooltip.classList.add('tooltip', `tooltip_theme_${options.theme}`);
 | 
			
		||||
            Object.assign($el._tooltip.$tooltip.style, { zIndex: options.zIndex });
 | 
			
		||||
            $el._tooltip.$tooltip.innerHTML = `
 | 
			
		||||
                ${
 | 
			
		||||
                    options.interactive
 | 
			
		||||
                        ? `
 | 
			
		||||
                            <div
 | 
			
		||||
                                class="tooltip__interactive-helper"
 | 
			
		||||
                                style="position: absolute; z-index; -1;">
 | 
			
		||||
                            </div>
 | 
			
		||||
                        `
 | 
			
		||||
                        : ''
 | 
			
		||||
                }
 | 
			
		||||
                ${
 | 
			
		||||
                    options.arrow
 | 
			
		||||
                        ? `
 | 
			
		||||
                            <div
 | 
			
		||||
                                class="tooltip__arrow"
 | 
			
		||||
                                style="pointer-events: none; position: absolute; transform: rotate(45deg);">
 | 
			
		||||
                            </div>
 | 
			
		||||
                        `
 | 
			
		||||
                        : ''
 | 
			
		||||
                }
 | 
			
		||||
                <div class="tooltip__container"></div>
 | 
			
		||||
                <div class="tooltip__root">
 | 
			
		||||
                    ${
 | 
			
		||||
                        options.interactive
 | 
			
		||||
                            ? `
 | 
			
		||||
                                <div
 | 
			
		||||
                                    class="tooltip__interactive-helper"
 | 
			
		||||
                                    style="position: absolute; z-index; -1;">
 | 
			
		||||
                                </div>
 | 
			
		||||
                            `
 | 
			
		||||
                            : ''
 | 
			
		||||
                    }
 | 
			
		||||
                    ${
 | 
			
		||||
                        options.arrow
 | 
			
		||||
                            ? `
 | 
			
		||||
                                <div
 | 
			
		||||
                                    class="tooltip__arrow"
 | 
			
		||||
                                    style="pointer-events: none; position: absolute; transform: rotate(45deg);">
 | 
			
		||||
                                </div>
 | 
			
		||||
                            `
 | 
			
		||||
                            : ''
 | 
			
		||||
                    }
 | 
			
		||||
                    <div class="tooltip__container"></div>
 | 
			
		||||
                </div>
 | 
			
		||||
            `;
 | 
			
		||||
            $el._tooltip.setContent();
 | 
			
		||||
 | 
			
		||||
@@ -272,51 +277,59 @@ export const createTooltip = ($el, content, options) => {
 | 
			
		||||
 | 
			
		||||
        const { autoUpdate } = await import('@floating-ui/dom');
 | 
			
		||||
 | 
			
		||||
        showTimeout = setTimeout(async () => {
 | 
			
		||||
            if (!$el._tooltip.isVisible) {
 | 
			
		||||
                options.appendTo.append($el._tooltip.$tooltip);
 | 
			
		||||
                $el._tooltip.isVisible = true;
 | 
			
		||||
                autoUpdateCleanup = autoUpdate($el, $el._tooltip.$tooltip, $el._tooltip.updatePosition);
 | 
			
		||||
        showTimeout = setTimeout(
 | 
			
		||||
            async () => {
 | 
			
		||||
                if (!$el._tooltip.isVisible) {
 | 
			
		||||
                    options.appendTo.append($el._tooltip.$tooltip);
 | 
			
		||||
                    $el._tooltip.isVisible = true;
 | 
			
		||||
                    autoUpdateCleanup = autoUpdate($el, $el._tooltip.$tooltip, $el._tooltip.updatePosition);
 | 
			
		||||
 | 
			
		||||
                if (options.onShow) {
 | 
			
		||||
                    options.onShow($el._tooltip);
 | 
			
		||||
                    if (options.onShow) {
 | 
			
		||||
                        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;
 | 
			
		||||
 | 
			
		||||
                    if (options.onShown) {
 | 
			
		||||
                        options.onShown($el._tooltip);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await $el._tooltip.$tooltip.animate([{ opacity: 0 }, { opacity: 1 }], {
 | 
			
		||||
                    duration: options.duration[1],
 | 
			
		||||
                    easing: options.easing[1],
 | 
			
		||||
                }).finished;
 | 
			
		||||
 | 
			
		||||
                if (options.onShown) {
 | 
			
		||||
                    options.onShown($el._tooltip);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, options.delay[0]);
 | 
			
		||||
            },
 | 
			
		||||
            immediately ? 0 : options.delay[0],
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $el._tooltip.hide = () => {
 | 
			
		||||
    $el._tooltip.hide = (params = {}) => {
 | 
			
		||||
        const { immediately } = params;
 | 
			
		||||
 | 
			
		||||
        clearTimeout(showTimeout);
 | 
			
		||||
 | 
			
		||||
        hideTimeout = setTimeout(async () => {
 | 
			
		||||
            if ($el._tooltip.isVisible) {
 | 
			
		||||
                if (options.onHide) {
 | 
			
		||||
                    options.onHide($el._tooltip);
 | 
			
		||||
        hideTimeout = setTimeout(
 | 
			
		||||
            async () => {
 | 
			
		||||
                if ($el._tooltip.isVisible) {
 | 
			
		||||
                    if (options.onHide) {
 | 
			
		||||
                        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;
 | 
			
		||||
 | 
			
		||||
                    $el._tooltip.$tooltip.remove();
 | 
			
		||||
                    $el._tooltip.isVisible = false;
 | 
			
		||||
                    autoUpdateCleanup();
 | 
			
		||||
 | 
			
		||||
                    if (options.onHidden) {
 | 
			
		||||
                        options.onHidden($el._tooltip);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await $el._tooltip.$tooltip.animate([{ opacity: 1 }, { opacity: 0 }], {
 | 
			
		||||
                    duration: options.duration[1],
 | 
			
		||||
                    easing: options.easing[1],
 | 
			
		||||
                }).finished;
 | 
			
		||||
 | 
			
		||||
                $el._tooltip.$tooltip.remove();
 | 
			
		||||
                $el._tooltip.isVisible = false;
 | 
			
		||||
                autoUpdateCleanup();
 | 
			
		||||
 | 
			
		||||
                if (options.onHidden) {
 | 
			
		||||
                    options.onHidden($el._tooltip);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, options.delay[1]);
 | 
			
		||||
            },
 | 
			
		||||
            immediately ? 0 : options.delay[1],
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const hideOnClickListener = ({ target }) => {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user