UNPKG

@atlaskit/tooltip

Version:

A tooltip briefly describes an interactive element on mouse hover or keyboard focus.

170 lines (161 loc) 4.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.show = show; var _fg = require("@atlaskit/platform-feature-flags/fg"); var delayId = null; function clearScheduled() { if (delayId != null) { window.clearTimeout(delayId); delayId = null; } } function scheduleTimeout(fn, delay) { clearScheduled(); delayId = window.setTimeout(function () { delayId = null; fn(); }, delay); } // This file is a singleton for managing tooltips. // // Once we roll out top-layer and remove the legacy path, this manager can be simplified: // - Singleton: Can be removed; the platform (popover="auto" or popover="hint") already enforces // only one tooltip open at a time. // - Phase machine: Can be simplified; drop hide-animating and finishHideAnimation (legacy fade-out). // Use e.g. pending-show | visible | pending-hide with immediate hide. // - API: Can drop or simplify mousePosition/mousePos if no longer needed; keep delay scheduling, // keep(), requestHide, abort, and minimal lifecycle. var active = null; function show(entry) { var phase = 'waiting-to-show'; function isActive() { return Boolean(active && active.entry === entry); } function cleanup() { if (isActive()) { clearScheduled(); active = null; } } function done() { if (isActive()) { entry.done(); } phase = 'done'; cleanup(); } function immediatelyHideAndDone() { if (isActive()) { entry.hide({ isImmediate: true }); } done(); } function keep() { if (!isActive()) { return; } // aborting a wait to hide if (phase === 'waiting-to-hide') { phase = 'shown'; clearScheduled(); return; } // aborting hide animation if (phase === 'hide-animating') { phase = 'shown'; clearScheduled(); entry.show({ isImmediate: false }); return; } } function requestHide(_ref) { var isImmediate = _ref.isImmediate; if (!isActive()) { return; } // If we were not showing yet anyway; finish straight away if (phase === 'waiting-to-show') { immediatelyHideAndDone(); return; } // already waiting to hide // Bug in legacy path: isImmediate hide requests are ignored during waiting-to-hide, // meaning Escape/scroll won't instantly dismiss a tooltip that's already fading out. // Gated fix: only apply the immediate-hide behavior under the top-layer flag for now. if (phase === 'waiting-to-hide') { if (isImmediate && (0, _fg.fg)('platform-dst-top-layer-tooltip')) { immediatelyHideAndDone(); } return; } if (isImmediate) { immediatelyHideAndDone(); return; } phase = 'waiting-to-hide'; scheduleTimeout(function () { phase = 'hide-animating'; entry.hide({ isImmediate: false }); }, entry.delay); } function finishHideAnimation() { if (isActive() && phase === 'hide-animating') { done(); } } function isVisible() { return phase === 'shown' || phase === 'waiting-to-hide' || phase === 'hide-animating'; } function start() { var shouldAlwaysFadeIn = entry.shouldAlwaysFadeIn; var showImmediately = Boolean(active && active.isVisible()) && !shouldAlwaysFadeIn; // If there was an active tooltip; we tell it to remove itself at once! if (active) { clearScheduled(); active.entry.hide({ isImmediate: true }); active.entry.done(); active = null; } // this tooltip is now the active tooltip active = { entry: entry, isVisible: isVisible }; function show() { phase = 'shown'; entry.show({ isImmediate: showImmediately }); } if (showImmediately) { show(); return; } phase = 'waiting-to-show'; scheduleTimeout(show, entry.delay); } // let's get started! start(); var result = { keep: keep, abort: cleanup, isActive: isActive, requestHide: requestHide, finishHideAnimation: finishHideAnimation, mousePos: entry.source.type === 'mouse' ? { clientX: entry.source.clientX, clientY: entry.source.clientY } : null }; return result; }