/** * InterestInvoker * ----------------------------------------------------------------------------- * Framework-agnostic controller that gives any host element "interest invoker" * behaviour — hover / keyboard-focus driven show & hide of a target popover — * by borrowing the `interestfor` attribute convention from the proposed Interest * Invokers API, WITHOUT depending on the (Chromium-only) native implementation * or any global polyfill. Your components own the behaviour; it works in every * browser by construction. * * Usage (Stencil): * * private interest = new InterestInvoker(); // inline field, no host dependency * connectedCallback() { this.interest.connect(this.host); } * disconnectedCallback() { this.interest.disconnect(); } * * The host is supplied to connect() — NOT the constructor — because Stencil does * not assign the @Element() host reference until ~connectedCallback. Reading it * in a field initialiser (constructor time) yields undefined and trips * "Property 'host' is used before its initialization". * * Known limitations (deliberate — decide these per component, don't assume): * - Touch: long-press activation is intentionally NOT implemented. The native * spec itself has not resolved touch (suppressing the context menu is the * blocker), so a half-measure here would fight platform gestures. Add a * deliberate tap/long-press strategy if your components need it, and never * make a tooltip the ONLY path to essential information. * - Interactive popovers: blur on the host hides the target, so tabbing INTO an * interactive hovercard will close it. Fine for plain text tooltips; if the * target holds focusable content, extend this to keep alive while focus is * within the target. * - Hover bridge covers a direct pointer move onto the target, not the diagonal * "safe triangle" path. The hideDelay grace period absorbs most of the gap. */ /** Contract the target element (e.g. ) must implement. */ export interface InterestTarget extends HTMLElement { showInterest?(source: HTMLElement): void; loseInterest?(): void; } export interface InterestInvokerOptions { /** Attribute read from the host to find the target's id. Default: 'interestfor'. */ attribute?: string; /** Delay before showing, in ms. Default: 300. */ showDelay?: number; /** Grace period before hiding — lets the pointer travel onto the target. Default: 100. */ hideDelay?: number; } export declare class InterestInvoker { private host; private readonly attribute; private readonly showDelay; private readonly hideDelay; private target; private showTimer?; private hideTimer?; private connected; constructor(options?: InterestInvokerOptions); /** Wire up the host. Call from connectedCallback(). Idempotent. */ connect(host: HTMLElement): void; /** Tear down. Call from disconnectedCallback(). */ disconnect(): void; /** * Re-read the target reference. Call from a @Watch('interestFor') handler if * the attribute can change at runtime. */ refresh(): void; /** Resolve the target lazily so targets added to the DOM after connect() are found. */ private resolveTarget; private onShow; private onScheduleHide; private onKeydown; private hide; private detachTargetBridge; private clearTimer; private clearTimers; }