diff --git a/README.md b/README.md index 45c088e..4046b56 100644 --- a/README.md +++ b/README.md @@ -138,20 +138,22 @@ yarn add @untemps/svelte-use-tooltip ## API -| Props | Type | Default | Description | -|---------------------------|---------|-------------------|-----------------------------------------------------------------------------------------------------------------| -| `content` | string | null | Text content to display in the tooltip. | -| `contentSelector` | string | null | Selector of the content to display in the tooltip. | -| `contentActions` | object | null | Configuration of the tooltip actions (see [Content Actions](#content-actions)). | -| `containerClassName` | string | '__tooltip' | Class name to apply to the tooltip container. | -| `position` | string | 'top' | Position of the tooltip. Available values: 'top', 'bottom', 'left', 'right' | -| `animated` | boolean | false | Flag to animate tooltip transitions. | -| `animationEnterClassName` | string | '__tooltip-enter' | Class name to apply to the tooltip enter transition. | -| `animationLeaveClassName` | string | '__tooltip-leave' | Class name to apply to the tooltip leave transition. | -| `enterDelay` | number | 0 | Delay before showing the tooltip in milliseconds. | -| `leaveDelay` | number | 0 | Delay before hiding the tooltip in milliseconds. | -| `offset` | number | 10 | Distance between the tooltip and the target in pixels. | -| `disabled` | boolean | false | Flag to disable the tooltip content. | +| Props | Type | Default | Description | +|---------------------------|---------|-------------------|---------------------------------------------------------------------------------| +| `content` | string | null | Text content to display in the tooltip. | +| `contentSelector` | string | null | Selector of the content to display in the tooltip. | +| `contentActions` | object | null | Configuration of the tooltip actions (see [Content Actions](#content-actions)). | +| `containerClassName` | string | '__tooltip' | Class name to apply to the tooltip container. | +| `position` | string | 'top' | Position of the tooltip. Available values: 'top', 'bottom', 'left', 'right' | +| `animated` | boolean | false | Flag to animate tooltip transitions. | +| `animationEnterClassName` | string | '__tooltip-enter' | Class name to apply to the tooltip enter transition. | +| `animationLeaveClassName` | string | '__tooltip-leave' | Class name to apply to the tooltip leave transition. | +| `enterDelay` | number | 0 | Delay before showing the tooltip in milliseconds. | +| `leaveDelay` | number | 0 | Delay before hiding the tooltip in milliseconds. | +| `onEnter` | func | null | Callback triggered when the tooltip appears. | +| `onLeave` | func | null | Callback triggered when the tooltip disappears. | +| `offset` | number | 10 | Distance between the tooltip and the target in pixels. | +| `disabled` | boolean | false | Flag to disable the tooltip content. | ### Content and Content Selector diff --git a/dev/src/App.svelte b/dev/src/App.svelte index 53c71b5..2311d2a 100644 --- a/dev/src/App.svelte +++ b/dev/src/App.svelte @@ -6,16 +6,30 @@ let showSettings = false - let tooltipTextContent = null - let useCustomTooltipClass = false - let tooltipPosition = 'top' - let isTooltipDisabled = false - let animateTooltip = false + let textContent = null + let useCustomClass = false + let position = 'top' + let isDisabled = false + let animate = false let useCustomAnimationEnterClass = false let useCustomAnimationLeaveClass = false - let tooltipEnterDelay = 200 - let tooltipLeaveDelay = 200 - let tooltipOffset = 10 + let enterDelay = 200 + let leaveDelay = 200 + let triggerOnEnter = false + let triggerOnLeave = false + let offset = 10 + + const _onTooltipEnter = () => { + if(triggerOnEnter) { + alert('You\'ve entered the target') + } + } + + const _onTooltipLeave = () => { + if(triggerOnLeave) { + alert('You\'ve left the target') + } + } const _onTooltipClick = (arg, e) => { e.preventDefault() @@ -204,20 +218,20 @@
+
+
+ +
+
+
@@ -276,9 +302,9 @@
diff --git a/package.json b/package.json index 2ce5d8a..0f143c0 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@testing-library/dom": "^8.11.3", "@testing-library/jest-dom": "^5.11.6", "@testing-library/svelte": "^3.0.3", - "@untemps/utils": "^2.0.0-beta.1", + "@untemps/utils": "^2.4.0", "babel-jest": "^28.0.0-alpha.11", "cross-env": "^7.0.3", "husky": "^7.0.4", @@ -61,6 +61,7 @@ }, "dependencies": { "@untemps/dom-observer": "^2.0.0", + "@untemps/utils": "^2.4.0", "svelte": "3.49.0" }, "jest": { diff --git a/src/Tooltip.js b/src/Tooltip.js index 098178e..9c8d10f 100644 --- a/src/Tooltip.js +++ b/src/Tooltip.js @@ -1,4 +1,5 @@ import { DOMObserver } from '@untemps/dom-observer' +import { standby } from '@untemps/utils/async/standby' class Tooltip { static #instances = [] @@ -16,6 +17,8 @@ class Tooltip { #animationLeaveClassName = null #enterDelay = 0 #leaveDelay = 0 + #onEnter = null + #onLeave = null #offset = 10 #observer = null @@ -46,6 +49,8 @@ class Tooltip { animationLeaveClassName, enterDelay, leaveDelay, + onEnter, + onLeave, offset, disabled ) { @@ -60,6 +65,8 @@ class Tooltip { this.#animationLeaveClassName = animationLeaveClassName || '__tooltip-leave' this.#enterDelay = enterDelay || 0 this.#leaveDelay = leaveDelay || 0 + this.#onEnter = onEnter || null + this.#onLeave = onLeave || null this.#offset = Math.max(offset || 10, 5) this.#observer = new DOMObserver() @@ -86,6 +93,8 @@ class Tooltip { animationLeaveClassName, enterDelay, leaveDelay, + onEnter, + onLeave, offset, disabled ) { @@ -109,6 +118,8 @@ class Tooltip { this.#animationLeaveClassName = animationLeaveClassName || '__tooltip-leave' this.#enterDelay = enterDelay || 0 this.#leaveDelay = leaveDelay || 0 + this.#onEnter = onEnter || null + this.#onLeave = onLeave || null this.#offset = Math.max(offset || 10, 5) if (hasContentChanged || hasPositionChanged || hasOffsetChanged) { @@ -366,6 +377,8 @@ class Tooltip { if (this.#target === e.target) { await this.#waitForDelay(this.#enterDelay) await this.#appendTooltipToTarget() + await standby(0) + this.#onEnter?.() } } @@ -373,6 +386,8 @@ class Tooltip { if (this.#target === e.target || !this.#target.contains(e.target)) { await this.#waitForDelay(this.#leaveDelay) await this.#removeTooltipFromTarget() + await standby(0) + this.#onLeave?.() } } diff --git a/src/__tests__/useTooltip.test.js b/src/__tests__/useTooltip.test.js index c8e97cb..1359101 100644 --- a/src/__tests__/useTooltip.test.js +++ b/src/__tests__/useTooltip.test.js @@ -421,6 +421,30 @@ describe('useTooltip', () => { }) }) + describe('useTooltip props: onEnter', () => { + it('Triggers callback when entering tooltip', async () => { + const onEnter = jest.fn() + action = useTooltip(target, { + ...options, + onEnter, + }) + await _enter(target) + await standby(0) + expect(onEnter).toHaveBeenCalled() + }) + + it('Triggers callback when entering tooltip after update', async () => { + const onEnter = jest.fn() + action = useTooltip(target, options) + action.update({ + onEnter, + }) + await _enter(target) + await standby(0) + expect(onEnter).toHaveBeenCalled() + }) + }) + describe('useTooltip props: leaveDelay', () => { it('Delays tooltip disappearance', async () => { action = useTooltip(target, { diff --git a/src/useTooltip.js b/src/useTooltip.js index 68ca90c..75c9ac0 100644 --- a/src/useTooltip.js +++ b/src/useTooltip.js @@ -15,6 +15,8 @@ const useTooltip = ( animationLeaveClassName, enterDelay, leaveDelay, + onEnter, + onLeave, offset, disabled, } @@ -31,6 +33,8 @@ const useTooltip = ( animationLeaveClassName, enterDelay, leaveDelay, + onEnter, + onLeave, offset, disabled ) @@ -47,6 +51,8 @@ const useTooltip = ( animationLeaveClassName: newAnimationLeaveClassName, enterDelay: newEnterDelay, leaveDelay: newLeaveDelay, + onEnter: newOnEnter, + onLeave: newOnLeave, offset: newOffset, disabled: newDisabled, }) => @@ -61,6 +67,8 @@ const useTooltip = ( newAnimationLeaveClassName, newEnterDelay, newLeaveDelay, + newOnEnter, + newOnLeave, newOffset, newDisabled ), diff --git a/yarn.lock b/yarn.lock index 79013a4..d174b2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2365,10 +2365,10 @@ resolved "https://registry.yarnpkg.com/@untemps/dom-observer/-/dom-observer-2.0.0.tgz#5b86b091f62905a6f18b0280bbf9067f2949716f" integrity sha512-oZBj7j9hYSbuveNFvyPLamRfNh15KvGJC5pLGGpWVcO61EzISMESL0wudwP0UZETEu+0WfaJ16rGXtEZHsq+xw== -"@untemps/utils@^2.0.0-beta.1": - version "2.0.0-beta.1" - resolved "https://registry.yarnpkg.com/@untemps/utils/-/utils-2.0.0-beta.1.tgz#c7369b7efb06d0b7283e81e09d42207240dd9f8a" - integrity sha512-XwZzhIRcjDA2em+fGNLjbSqnq8UD5GtqqeENtuQAn73ztcGZCX/5eAhL9BK63wgnalwOO3wN+y9SfN+IXYjt4Q== +"@untemps/utils@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@untemps/utils/-/utils-2.4.0.tgz#56d47022f289d7c1578d587d33c922d494b921f1" + integrity sha512-SC8iU/J0HLXaDBd1NiXu4Tgal0WaeMIEDP4aaX/aotD8iwLi7vfihGwm970ATHZJphPheuPPZM9igsD4scr9og== dependencies: "@babel/runtime" "^7.17.8"