UNPKG

monaco-editor-core

Version:

A browser based code editor

93 lines (92 loc) 3.89 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { isHTMLElement } from '../../../../base/browser/dom.js'; import { CancellationTokenSource } from '../../../../base/common/cancellation.js'; import { isMarkdownString } from '../../../../base/common/htmlContent.js'; import { isFunction, isString } from '../../../../base/common/types.js'; import { localize } from '../../../../nls.js'; export class ManagedHoverWidget { constructor(hoverDelegate, target, fadeInAnimation) { this.hoverDelegate = hoverDelegate; this.target = target; this.fadeInAnimation = fadeInAnimation; } async update(content, focus, options) { if (this._cancellationTokenSource) { // there's an computation ongoing, cancel it this._cancellationTokenSource.dispose(true); this._cancellationTokenSource = undefined; } if (this.isDisposed) { return; } let resolvedContent; if (content === undefined || isString(content) || isHTMLElement(content)) { resolvedContent = content; } else if (!isFunction(content.markdown)) { resolvedContent = content.markdown ?? content.markdownNotSupportedFallback; } else { // compute the content, potentially long-running // show 'Loading' if no hover is up yet if (!this._hoverWidget) { this.show(localize('iconLabel.loading', "Loading..."), focus, options); } // compute the content this._cancellationTokenSource = new CancellationTokenSource(); const token = this._cancellationTokenSource.token; resolvedContent = await content.markdown(token); if (resolvedContent === undefined) { resolvedContent = content.markdownNotSupportedFallback; } if (this.isDisposed || token.isCancellationRequested) { // either the widget has been closed in the meantime // or there has been a new call to `update` return; } } this.show(resolvedContent, focus, options); } show(content, focus, options) { const oldHoverWidget = this._hoverWidget; if (this.hasContent(content)) { const hoverOptions = { content, target: this.target, actions: options?.actions, linkHandler: options?.linkHandler, trapFocus: options?.trapFocus, appearance: { showPointer: this.hoverDelegate.placement === 'element', skipFadeInAnimation: !this.fadeInAnimation || !!oldHoverWidget, // do not fade in if the hover is already showing showHoverHint: options?.appearance?.showHoverHint, }, position: { hoverPosition: 2 /* HoverPosition.BELOW */, }, }; this._hoverWidget = this.hoverDelegate.showHover(hoverOptions, focus); } oldHoverWidget?.dispose(); } hasContent(content) { if (!content) { return false; } if (isMarkdownString(content)) { return !!content.value; } return true; } get isDisposed() { return this._hoverWidget?.isDisposed; } dispose() { this._hoverWidget?.dispose(); this._cancellationTokenSource?.dispose(true); this._cancellationTokenSource = undefined; } }