import { ComponentId } from '../dataModels'; import { ComponentBase, ComponentState } from './componentBase'; import { PopupManager } from '../popupManager'; export type TooltipState = ComponentState & { _type_: 'Tooltip-builtin'; anchor?: ComponentId; _tip_component?: ComponentId | null; position?: 'auto' | 'left' | 'top' | 'right' | 'bottom'; gap?: number; }; export class TooltipComponent extends ComponentBase { state: Required; private anchorContainer: HTMLElement; private labelElement: HTMLElement; private popupManager: PopupManager; createElement(): HTMLElement { // Set up the HTML let element = document.createElement('div'); element.classList.add('rio-tooltip'); element.innerHTML = `
`; this.anchorContainer = element.querySelector( '.rio-tooltip-anchor' ) as HTMLElement; this.labelElement = element.querySelector( '.rio-tooltip-label' ) as HTMLElement; // Listen for events this.anchorContainer.addEventListener('mouseover', () => { this.popupManager.setOpen(true); }); this.anchorContainer.addEventListener('mouseout', () => { this.popupManager.setOpen(false); }); // Initialize the popup manager. Many of these values will be // overwritten by the updateElement method. this.popupManager = new PopupManager( this.anchorContainer, this.labelElement, 'center', 0.5, 0.0 ); return element; } updateElement( deltaState: TooltipState, latentComponents: Set ): void { super.updateElement(deltaState, latentComponents); // Update the anchor if (deltaState.anchor !== undefined) { this.replaceOnlyChild( latentComponents, deltaState.anchor, this.anchorContainer ); } // Update tip if (deltaState._tip_component !== undefined) { this.replaceOnlyChild( latentComponents, deltaState._tip_component, this.labelElement ); } // Position if (deltaState.position !== undefined) { this.popupManager.position = deltaState.position; } // Gap if (deltaState.gap !== undefined) { this.popupManager.gap = deltaState.gap; } } onDestruction(): void { super.onDestruction(); this.popupManager.destroy(); } }