import * as _angular_core from '@angular/core'; import { OnInit, OnDestroy, ElementRef, Signal, TemplateRef } from '@angular/core'; import { Observable } from 'rxjs'; type Placement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'right' | 'right-start' | 'right-end' | 'left' | 'left-start' | 'left-end'; /** * The events and timings a callout opens and closes with. Each directive supplies these as its defaults, and the * base resolves them against whatever the consumer bound */ interface ICalloutTriggers { delay: number; openEvents: string[]; closeEvents: string[]; closeOnScroll: boolean; pointerEvents: 'auto' | 'none'; } /** * The overlay engine behind `nwTooltip` and `nwPopover`: it positions a callout against a host element, opens and * closes it on the configured events, and renders the content into a `TooltipContainerComponent`. * * It has no selector and is abstract, so it cannot be attached to an element. What a callout *means* - whether it is * a description of its host or a dialog the user opens - is decided by the subclass through `_onCalloutOpened`. Neither * subclass can reach the other's behaviour */ declare abstract class CalloutBaseDirective implements OnInit, OnDestroy { protected _elRef: ElementRef; private _overlay; private _vcRef; private _injector; /** * The id of the callout element, so that it can be referenced by `aria-describedby`. From the CDK generator * rather than a module-level counter, so that ids stay unique across two copies of the library on one page and * stable between a server render and its hydration */ protected readonly _calloutId: string; /** * An object that can be passed when the content is a `TemplateRef` * ref: https://angular.io/api/core/ng-template#context */ readonly context: _angular_core.InputSignal; /** One or more preferred placement options */ readonly placement: _angular_core.InputSignal; /** Manually control the opening and closing of the callout */ readonly isOpen: _angular_core.InputSignal; /** * When true, the callout will not respond to any open or close events. Nor will it respond to changes to the * `isOpen` input */ readonly isDisabled: _angular_core.InputSignal; /** Number of ms to wait before opening. Defaults per kind of callout - see `_getTriggerDefaults` */ readonly delay: _angular_core.InputSignal; /** Change the placement of the callout to its opposite position when it moves outside the viewport */ readonly autoFlip: _angular_core.InputSignal; /** A list of events that open the callout */ readonly openEvents: _angular_core.InputSignal; /** A list of events that close the callout */ readonly closeEvents: _angular_core.InputSignal; /** A class to apply to the callout container */ readonly containerClass: _angular_core.InputSignal; /** Display an arrow or not. The location of the arrow is dependant on the current `placement` */ readonly withArrow: _angular_core.InputSignal; readonly closeOnScroll: _angular_core.InputSignal; /** * WARNING: Use with caution - there are potential performance issues with this * * Update the position of the callout before the next browser repaint. An example of where this may be required is * if the callout is attached (and open) to an element that transitions or animates to a new position */ readonly updatePositionOnAnimationFrame: _angular_core.InputSignal; /** * In the case where the callout should not be attached to the host element, a reference to another element can be * used */ readonly connectedTo: _angular_core.InputSignal>; /** Determines whether pointer events are enabled on the cdk-overlay-pane element */ readonly pointerEvents: _angular_core.InputSignal<"auto" | "none">; readonly hostElementZIndex: _angular_core.InputSignal; readonly nwShown: _angular_core.OutputEmitterRef; readonly nwHidden: _angular_core.OutputEmitterRef; readonly nwClose: _angular_core.OutputEmitterRef; /** * `isOpen` as a stream, so that manual control joins the same pipeline as every other open and close event. * Undefined is filtered out: an unbound `isOpen` should say nothing rather than assert that it is closed */ private readonly _isOpen$; /** * The strategies the CDK needs, derived rather than rebuilt on demand. Both are memoised, and the CDK ignores * an update that hands it the strategy it already has */ private readonly _positionStrategy; private readonly _scrollStrategy; /** * The events and timings this callout actually opens with: what the consumer bound, falling back to the * defaults for its kind. Derived rather than assigned, so that a rebound input still wins */ protected readonly _triggers: Signal; private _overlayRef; private _destroyed$; private _cancelDelayedOpen$; /** The `.tooltip` element of the open callout */ protected _calloutEl: HTMLElement | null; private _manualToggleEvent$; /** Emits only where the subclass opted into outside-click dismissal - see `_open` */ private _outsideClick$; /** Set while the directive is being torn down, so that closing does not act on a host that is going away */ protected _isDestroyed: boolean; /** The content, which each subclass declares as its own input under its own selector */ protected abstract readonly _content: Signal>; /** The events, delay and pointer behaviour this kind of callout opens with */ protected abstract _getTriggerDefaults(): ICalloutTriggers; /** * Expose the callout to assistive technology, once its content has rendered. This is the whole of the difference * between a tooltip and a popover */ protected abstract _onCalloutOpened(calloutEl: HTMLElement): void; /** Any key other than Escape that this kind of callout responds to, while it is open */ protected _onCalloutKeydown(_event: KeyboardEvent): void; /** Undo whatever `_onCalloutOpened` did, as the callout closes */ protected _onCalloutClosing(): void; /** Whether the callout renders a close button. Only a popover does */ protected _hasCloseButton(): boolean; /** Whether a pointer event outside the callout closes it */ protected _dismissesOnOutsideClick(): boolean; /** Any further open or close events the subclass contributes, e.g. a tooltip opening on keyboard focus */ protected _getAdditionalToggleEvents(): Observable; constructor(); ngOnInit(): void; /** * Can be called manually from the exported directive to open the callout */ show(): void; /** * Can be called manually from the exported directive to close the callout */ hide(): void; /** * Can be called manually from the exported directive to toggle the callout */ toggle(): void; /** Attaches the callout, returning its container - or null where it was already open */ private _open; /** * Escape closes any callout, which is required of content that appears on hover or focus * ref: https://www.w3.org/WAI/WCAG21/Understanding/content-on-hover-or-focus.html * * Every other key is the subclass's to answer, if it answers any */ private _subscribeToCalloutKeydown; /** * A pointer event anywhere but the callout and its host closes the callout, for the subclasses that ask for it */ private _subscribeToOutsidePointerEvents; protected _close(): void; private _createOverlay; /** * Create and return a custom injector that provides the callout content as an injectable dependency */ private _createInjector; /** * The one subscription that opens and closes the callout, from every source that can ask for either */ private _subscribeToEvents; /** * Every source that can open or close the callout, as a single stream of whether it should now be open. * `_outsideClick$` is included unconditionally, as `_open` is what decides whether anything pushes into it */ private _getToggleEvents$; /** The host events that open the callout, ignored while it is already open */ private _getOpenEvents$; /** The host events that close the callout. They also cancel an open that is still waiting out its delay */ private _getCloseEvents$; /** * Whether the same event both opens and closes the callout - "click" in both lists, say - which fires the * merged stream twice within a few ms. The debounce this feeds keeps that from opening and instantly closing */ private _hasOverlappingToggleEvents; /** Hold an open event for `delay`, cancellable by a close event in the meantime. Closing is never delayed */ private _delayIfOpening; /** * Open the callout and hand it to the subclass to expose, which can only happen once its content has rendered */ private _openAndExpose; /** * Close on the container's own close button. Released with the container it belongs to, so that a callout * opened and closed repeatedly does not leave a subscription behind on each destroyed instance */ private _subscribeToContainerClose; /** * Follow a host that moves under its own steam - one that transitions or animates to a new position - by * repositioning before every repaint. Off by default: it costs a reposition per frame while the callout is open */ private _repositionOnEveryFrame; /** * The size of the arrow the callout has to be offset by, read from the `--tooltip-arrow-size` custom property * that `_tooltip.scss` publishes off `$tooltip-arrow-width`, so that overriding that variable moves the arrow * and the space reserved for it together. * * Read from the host rather than measured off the arrow itself, which is a zero-size CSS triangle that does * not exist yet: the offsets are baked into the position pairs before the callout is ever attached. * * Read once per strategy build rather than cached for the directive's life, so that a theme that retunes the * property at runtime is picked up the next time the strategy is rebuilt, while a single build still only asks * the one time for all of its candidate placements */ private _readArrowSize; private _getPositionPair; private _getPositionStrategy; private _getScrollStrategy; /** * `_close` rather than `hide`, which only asks the debounced pipeline to close and so would never arrive before * the subscription is torn down below. Going straight there also runs `_onCalloutClosing` exactly once, and only * where the callout was actually open - `hide` followed by an unconditional `_onCalloutClosing` did neither */ ngOnDestroy(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * A callout holding no interactive content, just a short piece of supplementary text about the element it is * attached to, opened by hovering the host or focusing it from the keyboard. * * The content reaches assistive technology through the host's `aria-describedby` whether the tooltip is open or not, * which matters because a screen reader user cannot hover to open it. A tooltip never takes focus, so anything in it * that could be operated would be unreachable - a callout holding a link or a button is a `nwPopover` */ declare class TooltipDirective extends CalloutBaseDirective implements OnDestroy { private _ariaDescriber; private _focusMonitor; readonly nwTooltip: _angular_core.InputSignal>; /** * Describe the host element with the content, so that screen reader users get it without opening the tooltip. * When not set, the description is skipped where the host's accessible name - its `aria-label`, or failing * that its visible text - is already the same text, so that it is not announced twice. Set it explicitly to * force the description on or off. Note that a description identical to the host's `aria-label` is dropped * by the CDK `AriaDescriber` itself, so `true` cannot force that case */ readonly withAriaDescription: _angular_core.InputSignal; /** * The screen width below which the tooltip opens on tap rather than on hover, as touch devices have no hover. * It stays a tooltip either way - only its events change. Set to 0 to always use the hover events */ readonly breakpoint: _angular_core.InputSignal; /** The last text handed to `_registerDescription`. Only registered with the `AriaDescriber` where it is non-empty */ private _describedText; protected readonly _content: Signal>; /** * Whether focus opens this tooltip: the keyboard equivalent of `mouseenter`, so it follows the hover events * rather than being bound separately. A manually controlled tooltip - one with no open events - is opened by * its host component alone, and a tap-to-open one below the `breakpoint` is opened by activating the host */ private readonly _opensOnFocus; /** The content as plain text, falsy where there is nothing to describe the host with */ private readonly _describableText; constructor(); protected _getTriggerDefaults(): ICalloutTriggers; /** * A tooltip has no outside-click behaviour of its own, but a tap-opened one on touch has no hover to end it, * so tapping elsewhere has to dismiss it */ protected _dismissesOnOutsideClick(): boolean; protected _onCalloutOpened(calloutEl: HTMLElement): void; protected _onCalloutClosing(): void; protected _getAdditionalToggleEvents(): Observable; /** * Emits true when the host is focused from the keyboard, and false when focus leaves it again */ private _getFocusEvents$; /** Point `aria-describedby` at the open callout. Only needed for a `TemplateRef`, which cannot be described */ private _setDescribedByCallout; /** Register text with the `AriaDescriber`, which adds it to the accessibility tree as a hidden node */ private _registerDescription; /** * An approximation of the host's accessible name: its `aria-label`, or failing that its visible text. Read * when the content changes, which covers hosts whose label and tooltip are bound to the same value; a label * that changes independently of the content is not re-read */ private _hostAccessibleName; private _normalize; /** * String content is rendered as HTML, so parse out its text. `DOMParser` in preference to an element's * `innerHTML`, as it creates an inert document that loads no resources. * * Normalised on the way out, so that it is directly comparable with the host's accessible name and so that * the indentation of multi-line content does not reach the description */ private _toPlainText; ngOnDestroy(): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * A callout that can hold interactive content - formatted text, links and buttons - toggled by clicking its host, * which should be a button and which the keyboard fires from Enter and Space. * * It is exposed as a small dialog, named after its trigger and described by its own content, and it announces * itself by taking focus. Focus is trapped there until it closes - on Escape, on the close button, or on a click * outside - and then returns to where it came from. Content that is only text and only needs describing belongs in * a `nwTooltip` instead */ declare class PopoverDirective extends CalloutBaseDirective { private _focusTrapFactory; private _interactivityChecker; readonly nwPopover: _angular_core.InputSignal>; /** Display a close button or not */ readonly withClose: _angular_core.InputSignal; readonly closeOnOutsideClick: _angular_core.InputSignal; private _focusTrap; /** The element focused before focus was moved into the callout */ private _previouslyFocusedEl; protected readonly _content: Signal>; protected _hasCloseButton(): boolean; protected _dismissesOnOutsideClick(): boolean; protected _getTriggerDefaults(): ICalloutTriggers; /** * Announce the trigger as one that opens a dialog, and as currently closed. Done up front rather than on the * first open, so that a screen reader user is told the control does something before they operate it */ ngOnInit(): void; /** * Name the callout after the host, announce it on the host, and move focus into it */ protected _onCalloutOpened(calloutEl: HTMLElement): void; /** * Release the focus trap, restoring focus unless the user has already moved it, e.g. by clicking outside */ protected _onCalloutClosing(): void; /** * Tabbing out of an untrapped callout would land at the end of the document, as the overlay is appended to the * body. Close and hand focus back to the host instead, so that tabbing carries on from where it left off */ protected _onCalloutKeydown(event: KeyboardEvent): void; /** * Trap focus, but only where there is something to trap it on: a trap around content with nothing tabbable in * it holds focus on its own hidden anchor, which reads as focus disappearing. Returns whether it trapped */ private _trapFocusIfThereIsSomethingToTrap; /** * Move focus to the callout, which is the only thing that announces it: a description added while it is open is * not read, as nothing re-reads a changed attribute. The callout itself is focused rather than the first thing * in it, so that its name is announced before its content, and so that long content can be read at the user's * own pace rather than in one unstoppable burst. * * Only done when focus is on the host, which means the user has just acted on it and following the callout * continues what they were doing. An open from the `isOpen` input or from `show()` while focus is elsewhere * must not take it - the docs page alone has popovers that are open from the moment it loads */ private _focusCalloutIfOpenedFromHost; /** An id for the host, so that the dialog can be labelled by it. Only generated if it has none */ private _getHostId; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } export { PopoverDirective, TooltipDirective }; export type { Placement };