v2.0.0
This commit is contained in:
parent
059831a412
commit
4323266d58
|
@ -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';
|
import { createTooltip } from '@advdominion/tooltip';
|
||||||
|
|
||||||
createTooltip(document.querySelector('button'), 'Подсказка', {
|
createTooltip(document.querySelector('button'), 'Подсказка', {
|
||||||
|
animation: [
|
||||||
|
[{ opacity: 0 }, { opacity: 1 }],
|
||||||
|
[{ opacity: 1 }, { opacity: 0 }],
|
||||||
|
],
|
||||||
appendTo: document.body,
|
appendTo: document.body,
|
||||||
arrow: true,
|
arrow: true,
|
||||||
delay: [0, 0],
|
delay: [0, 0],
|
||||||
|
@ -37,6 +41,7 @@ createTooltip(document.querySelector('button'), 'Подсказка', {
|
||||||
interactive: true,
|
interactive: true,
|
||||||
offset: [0, 8],
|
offset: [0, 8],
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
|
shiftPadding: [8, 0],
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
trigger: 'mouseenter',
|
trigger: 'mouseenter',
|
||||||
virtialReference: undefined,
|
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
|
##### setContent
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
@ -96,6 +127,12 @@ document.querySelector('button')._tooltip.updateOptions({ placement: 'bottom' })
|
||||||
<button type="button" data-tooltip-placement="bottom">Кнопка</button>
|
<button type="button" data-tooltip-placement="bottom">Кнопка</button>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### destroy
|
||||||
|
|
||||||
|
```js
|
||||||
|
document.querySelector('button')._tooltip.destroy();
|
||||||
|
```
|
||||||
|
|
||||||
### Стили
|
### Стили
|
||||||
|
|
||||||
```scss
|
```scss
|
||||||
|
@ -113,6 +150,9 @@ $b: '.tooltip';
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__root {
|
||||||
|
}
|
||||||
|
|
||||||
&__arrow {
|
&__arrow {
|
||||||
#{$b}_theme_light & {
|
#{$b}_theme_light & {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
117
index.js
117
index.js
|
@ -3,17 +3,27 @@ const roundByDPR = (value) => {
|
||||||
return Math.round(value * dpr) / dpr;
|
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) => {
|
export const createTooltip = ($el, content, options) => {
|
||||||
options = {
|
options = {
|
||||||
|
animation: [
|
||||||
|
[{ opacity: 0 }, { opacity: 1 }],
|
||||||
|
[{ opacity: 1 }, { opacity: 0 }],
|
||||||
|
],
|
||||||
appendTo: document.body,
|
appendTo: document.body,
|
||||||
arrow: true,
|
arrow: true,
|
||||||
delay: [0, 0],
|
delay: [0, 0],
|
||||||
duration: [0, 0],
|
duration: [0, 0],
|
||||||
easing: ['linear', 'linear'],
|
easing: ['linear', 'linear'],
|
||||||
hideOnClick: true,
|
hideOnClick: true, // Возможные значения: true, 'all', 'trigger'
|
||||||
interactive: true,
|
interactive: true,
|
||||||
offset: [0, 8],
|
offset: [0, 8],
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
|
shiftPadding: [8, 0],
|
||||||
theme: 'light',
|
theme: 'light',
|
||||||
trigger: 'mouseenter',
|
trigger: 'mouseenter',
|
||||||
virtialReference: undefined,
|
virtialReference: undefined,
|
||||||
|
@ -21,46 +31,29 @@ export const createTooltip = ($el, content, options) => {
|
||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($el.dataset.tooltipArrow !== undefined) {
|
const setOptionFromDataAttribute = (attribute) => {
|
||||||
options.arrow = $el.dataset.tooltipArrow === 'true';
|
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.tooltipHideOnClick !== undefined) {
|
setOptionFromDataAttribute('tooltipAnimation');
|
||||||
switch ($el.dataset.tooltipHideOnClick) {
|
setOptionFromDataAttribute('tooltipArrow');
|
||||||
case 'all':
|
setOptionFromDataAttribute('tooltipDelay');
|
||||||
case 'toggle': {
|
setOptionFromDataAttribute('tooltipDuration');
|
||||||
options.hideOnClick = $el.dataset.tooltipHideOnClick;
|
setOptionFromDataAttribute('tooltipEasing');
|
||||||
break;
|
setOptionFromDataAttribute('tooltipHideOnClick');
|
||||||
}
|
setOptionFromDataAttribute('tooltipInteractive');
|
||||||
default: {
|
setOptionFromDataAttribute('tooltipOffset');
|
||||||
options.hideOnClick = $el.dataset.tooltipHideOnClick === 'true';
|
setOptionFromDataAttribute('tooltipPlacement');
|
||||||
}
|
setOptionFromDataAttribute('tooltipShiftPadding');
|
||||||
}
|
setOptionFromDataAttribute('tooltipTheme');
|
||||||
}
|
setOptionFromDataAttribute('tooltipTrigger');
|
||||||
|
setOptionFromDataAttribute('tooltipZIndex');
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
let showTimeout;
|
let showTimeout;
|
||||||
let hideTimeout;
|
let hideTimeout;
|
||||||
|
@ -69,7 +62,7 @@ export const createTooltip = ($el, content, options) => {
|
||||||
const listeners = [];
|
const listeners = [];
|
||||||
|
|
||||||
$el._tooltip = {
|
$el._tooltip = {
|
||||||
_options: options,
|
options,
|
||||||
isVisible: false,
|
isVisible: false,
|
||||||
setContent(updatedContent) {
|
setContent(updatedContent) {
|
||||||
if (updatedContent !== undefined) {
|
if (updatedContent !== undefined) {
|
||||||
|
@ -159,13 +152,16 @@ export const createTooltip = ($el, content, options) => {
|
||||||
options.onCreate($el._tooltip);
|
options.onCreate($el._tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
$el._tooltip.show = async () => {
|
$el._tooltip.show = async (params = {}) => {
|
||||||
|
const { immediately } = params;
|
||||||
|
|
||||||
clearTimeout(hideTimeout);
|
clearTimeout(hideTimeout);
|
||||||
|
|
||||||
if (!$el._tooltip.$tooltip) {
|
if (!$el._tooltip.$tooltip) {
|
||||||
const { computePosition, offset, flip, shift, arrow } = await import('@floating-ui/dom');
|
const { computePosition, offset, flip, shift, arrow } = await import('@floating-ui/dom');
|
||||||
|
|
||||||
$el._tooltip.$tooltip = document.createElement('div');
|
$el._tooltip.$tooltip = document.createElement('div');
|
||||||
|
$el._tooltip.$tooltip._reference = $el;
|
||||||
$el._tooltip.updatePosition = async () => {
|
$el._tooltip.updatePosition = async () => {
|
||||||
const $arrow = $el._tooltip.$tooltip.querySelector('.tooltip__arrow');
|
const $arrow = $el._tooltip.$tooltip.querySelector('.tooltip__arrow');
|
||||||
|
|
||||||
|
@ -180,7 +176,14 @@ export const createTooltip = ($el, content, options) => {
|
||||||
crossAxis: options.offset[0],
|
crossAxis: options.offset[0],
|
||||||
}),
|
}),
|
||||||
flip(),
|
flip(),
|
||||||
shift(),
|
shift({
|
||||||
|
padding: {
|
||||||
|
top: options.shiftPadding[1],
|
||||||
|
right: options.shiftPadding[0],
|
||||||
|
bottom: options.shiftPadding[1],
|
||||||
|
left: options.shiftPadding[0],
|
||||||
|
},
|
||||||
|
}),
|
||||||
arrow({
|
arrow({
|
||||||
element: $arrow,
|
element: $arrow,
|
||||||
padding: Number.parseInt(
|
padding: Number.parseInt(
|
||||||
|
@ -241,6 +244,7 @@ export const createTooltip = ($el, content, options) => {
|
||||||
$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">
|
||||||
${
|
${
|
||||||
options.interactive
|
options.interactive
|
||||||
? `
|
? `
|
||||||
|
@ -262,6 +266,7 @@ export const createTooltip = ($el, content, options) => {
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
<div class="tooltip__container"></div>
|
<div class="tooltip__container"></div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
$el._tooltip.setContent();
|
$el._tooltip.setContent();
|
||||||
|
|
||||||
|
@ -272,7 +277,8 @@ export const createTooltip = ($el, content, options) => {
|
||||||
|
|
||||||
const { autoUpdate } = await import('@floating-ui/dom');
|
const { autoUpdate } = await import('@floating-ui/dom');
|
||||||
|
|
||||||
showTimeout = setTimeout(async () => {
|
showTimeout = setTimeout(
|
||||||
|
async () => {
|
||||||
if (!$el._tooltip.isVisible) {
|
if (!$el._tooltip.isVisible) {
|
||||||
options.appendTo.append($el._tooltip.$tooltip);
|
options.appendTo.append($el._tooltip.$tooltip);
|
||||||
$el._tooltip.isVisible = true;
|
$el._tooltip.isVisible = true;
|
||||||
|
@ -282,29 +288,34 @@ export const createTooltip = ($el, content, options) => {
|
||||||
options.onShow($el._tooltip);
|
options.onShow($el._tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
await $el._tooltip.$tooltip.animate([{ opacity: 0 }, { opacity: 1 }], {
|
await $el._tooltip.$tooltip.querySelector('.tooltip__root').animate(options.animation[0], {
|
||||||
duration: options.duration[1],
|
duration: immediately ? 0 : options.duration[0],
|
||||||
easing: options.easing[1],
|
easing: options.easing[0],
|
||||||
}).finished;
|
}).finished;
|
||||||
|
|
||||||
if (options.onShown) {
|
if (options.onShown) {
|
||||||
options.onShown($el._tooltip);
|
options.onShown($el._tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, options.delay[0]);
|
},
|
||||||
|
immediately ? 0 : options.delay[0],
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
$el._tooltip.hide = () => {
|
$el._tooltip.hide = (params = {}) => {
|
||||||
|
const { immediately } = params;
|
||||||
|
|
||||||
clearTimeout(showTimeout);
|
clearTimeout(showTimeout);
|
||||||
|
|
||||||
hideTimeout = setTimeout(async () => {
|
hideTimeout = setTimeout(
|
||||||
|
async () => {
|
||||||
if ($el._tooltip.isVisible) {
|
if ($el._tooltip.isVisible) {
|
||||||
if (options.onHide) {
|
if (options.onHide) {
|
||||||
options.onHide($el._tooltip);
|
options.onHide($el._tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
await $el._tooltip.$tooltip.animate([{ opacity: 1 }, { opacity: 0 }], {
|
await $el._tooltip.$tooltip.querySelector('.tooltip__root').animate(options.animation[1], {
|
||||||
duration: options.duration[1],
|
duration: immediately ? 0 : options.duration[1],
|
||||||
easing: options.easing[1],
|
easing: options.easing[1],
|
||||||
}).finished;
|
}).finished;
|
||||||
|
|
||||||
|
@ -316,7 +327,9 @@ export const createTooltip = ($el, content, options) => {
|
||||||
options.onHidden($el._tooltip);
|
options.onHidden($el._tooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, options.delay[1]);
|
},
|
||||||
|
immediately ? 0 : options.delay[1],
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const hideOnClickListener = ({ target }) => {
|
const hideOnClickListener = ({ target }) => {
|
||||||
|
|
Loading…
Reference in New Issue