diff --git a/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts b/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts index c10eb267a..8f577fb2d 100644 --- a/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts +++ b/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts @@ -86,6 +86,9 @@ export class SlickCustomTooltip { } as CustomTooltipOption; protected _grid!: SlickGrid; protected _eventHandler: SlickEventHandler; + protected _hideTooltipTimeout?: NodeJS.Timeout; + protected _autoHideTimeout?: NodeJS.Timeout; + protected _isMouseOverTooltip = false; constructor() { this._eventHandler = new SlickEventHandler(); @@ -150,10 +153,10 @@ export class SlickCustomTooltip { .subscribe(grid.onHeaderMouseOver, (e, args) => this.handleOnHeaderMouseOverByType(e, args, 'slick-header-column')) .subscribe(grid.onHeaderRowMouseEnter, (e, args) => this.handleOnHeaderMouseOverByType(e, args, 'slick-headerrow-column')) .subscribe(grid.onHeaderRowMouseOver, (e, args) => this.handleOnHeaderMouseOverByType(e, args, 'slick-headerrow-column')) - .subscribe(grid.onMouseLeave, this.hideTooltip.bind(this)) - .subscribe(grid.onHeaderMouseOut, this.hideTooltip.bind(this)) - .subscribe(grid.onHeaderRowMouseLeave, this.hideTooltip.bind(this)) - .subscribe(grid.onHeaderRowMouseOut, this.hideTooltip.bind(this)); + .subscribe(grid.onMouseLeave, this.handleOnMouseLeave.bind(this)) + .subscribe(grid.onHeaderMouseOut, this.handleOnMouseLeave.bind(this)) + .subscribe(grid.onHeaderRowMouseLeave, this.handleOnMouseLeave.bind(this)) + .subscribe(grid.onHeaderRowMouseOut, this.handleOnMouseLeave.bind(this)); } dispose(): void { @@ -161,6 +164,27 @@ export class SlickCustomTooltip { this.hideTooltip(); this._cancellablePromise = undefined; this._eventHandler.unsubscribeAll(); + + if (this._hideTooltipTimeout) { + clearTimeout(this._hideTooltipTimeout); + this._hideTooltipTimeout = undefined; + } + if (this._autoHideTimeout) { + clearTimeout(this._autoHideTimeout); + this._autoHideTimeout = undefined; + } + } + + protected handleOnMouseLeave(): void { + if (this._hideTooltipTimeout) { + clearTimeout(this._hideTooltipTimeout); + } + + this._hideTooltipTimeout = setTimeout(() => { + if (!this._isMouseOverTooltip) { + this.hideTooltip(); + } + }, 100); } /** @@ -170,9 +194,20 @@ export class SlickCustomTooltip { hideTooltip(): void { this._cancellablePromise?.cancel(); this._observable$?.unsubscribe(); + + if (this._hideTooltipTimeout) { + clearTimeout(this._hideTooltipTimeout); + this._hideTooltipTimeout = undefined; + } + if (this._autoHideTimeout) { + clearTimeout(this._autoHideTimeout); + this._autoHideTimeout = undefined; + } + const cssClasses = classNameToList(this.className).join('.'); const prevTooltip = document.body.querySelector(`.${cssClasses}${this.gridUidSelector}`); prevTooltip?.remove(); + this._isMouseOverTooltip = false; } getOptions(): CustomTooltipOption | undefined { @@ -484,6 +519,24 @@ export class SlickCustomTooltip { if (finalOutputText.toString()) { document.body.appendChild(this._tooltipElm); + this._tooltipElm.addEventListener('mouseenter', () => { + this._isMouseOverTooltip = true; + if (this._hideTooltipTimeout) { + clearTimeout(this._hideTooltipTimeout); + this._hideTooltipTimeout = undefined; + } + }); + + this._tooltipElm.addEventListener('mouseleave', () => { + this._isMouseOverTooltip = false; + this.hideTooltip(); + }); + + // Auto-hide tooltip after 3 seconds regardless of mouse position + this._autoHideTimeout = setTimeout(() => { + this.hideTooltip(); + }, 3000); + // reposition the tooltip on top of the cell that triggered the mouse over event this.reposition(cell);