import * as i0 from '@angular/core';
import { inject, ChangeDetectorRef, PLATFORM_ID, ChangeDetectionStrategy, Component, InjectionToken, ElementRef, ViewContainerRef, input, numberAttribute, effect, Directive } from '@angular/core';
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { Subject } from 'rxjs';
import { isPlatformBrowser, NgClass } from '@angular/common';
import { takeUntil } from 'rxjs/operators';
import { Directionality } from '@angular/cdk/bidi';

class TooltipContent {
    _changeDetectorRef = inject(ChangeDetectorRef);
    _platformId = inject(PLATFORM_ID);
    /** Message to display in the tooltip */
    message = '';
    /** Classes to be added to the tooltip. */
    tooltipClass = '';
    /** The timeout ID of any current timer set to show the tooltip */
    _showTimeoutId = null;
    /** The timeout ID of any current timer set to hide the tooltip */
    _hideTimeoutId = null;
    /** Property watched by the animation framework to show or hide the tooltip */
    _visibility = 'initial';
    /** Subject for notifying that the tooltip has been hidden from the view */
    _onHide = new Subject();
    /** Subject for notifying that the mouse has entered the tooltip content */
    _onMouseEnter = new Subject();
    /** Subject for notifying that the mouse has left the tooltip content */
    _onMouseLeave = new Subject();
    /** Amount of time (in ms) to wait after a mouseleave event before hiding the tooltip. */
    _mouseLeaveHideDelay = 0;
    ngOnDestroy() {
        this._onHide.complete();
        this._onMouseEnter.complete();
        this._onMouseLeave.complete();
        this._cancelPendingAnimations();
    }
    /**
     * Shows the tooltip with an animation delay.
     * @param delay Amount of milliseconds to the delay.
     */
    show(delay) {
        // Cancel any instances where the tooltip might be hiding
        this._cancelPendingAnimations();
        const handler = () => {
            this._visibility = 'visible';
            this._showTimeoutId = null;
            this._changeDetectorRef.markForCheck();
        };
        // Set the visibility of the tooltip after the delay
        if (isPlatformBrowser(this._platformId)) {
            this._showTimeoutId = window.setTimeout(handler, delay);
        }
        else {
            this._showTimeoutId = setTimeout(handler, delay);
        }
    }
    /**
     * Causes the tooltip to begin in hiding animation.
     * @param delay Amount of milliseconds to the delay.
     */
    hide(delay) {
        // Cancel any instances where the tooltip might be showing
        this._cancelPendingAnimations();
        const handler = () => {
            this._visibility = 'hidden';
            this._hideTimeoutId = null;
            this._changeDetectorRef.markForCheck();
        };
        // Set the visibility of the tooltip after the delay
        if (isPlatformBrowser(this._platformId)) {
            this._hideTimeoutId = window.setTimeout(handler, delay);
        }
        else {
            this._hideTimeoutId = setTimeout(handler, delay);
        }
    }
    /** Returns an observable that notifies when the tooltip has been hidden from view. */
    afterHidden() {
        return this._onHide.asObservable();
    }
    /** Returns an observable that notifies when the mouse enters the tooltip content. */
    mouseEntered() {
        return this._onMouseEnter.asObservable();
    }
    /** Returns an observable that notifies when the mouse leaves the tooltip content. */
    mouseLeft() {
        return this._onMouseLeave.asObservable();
    }
    /** Whether the tooltip is being displayed. */
    isVisible() {
        return this._visibility === 'visible';
    }
    _onTransitionEnd(event) {
        if (event.propertyName === 'opacity' && this._visibility === 'hidden') {
            this._onHide.next();
        }
    }
    /**
     * Interactions on the HTML body should close the tooltip immediately as a way of closing
     * tooltips when focus moves combined with clicking.
     */
    _handleBodyClick() {
        if (this.isVisible()) {
            this.hide(0);
        }
    }
    _handleMouseEnter() {
        this._onMouseEnter.next();
    }
    _handleMouseLeave() {
        this._onMouseLeave.next();
    }
    /**
     * Cancels any pending animation timers.
     */
    _cancelPendingAnimations() {
        if (this._showTimeoutId) {
            if (isPlatformBrowser(this._platformId)) {
                window.clearTimeout(this._showTimeoutId);
            }
            else {
                clearTimeout(this._showTimeoutId);
            }
            this._showTimeoutId = null;
        }
        if (this._hideTimeoutId) {
            if (isPlatformBrowser(this._platformId)) {
                window.clearTimeout(this._hideTimeoutId);
            }
            else {
                clearTimeout(this._hideTimeoutId);
            }
            this._hideTimeoutId = null;
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TooltipContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: TooltipContent, isStandalone: true, selector: "ngs-tooltip-content", host: { attributes: { "aria-hidden": "true" }, listeners: { "body:click": "this._handleBodyClick()", "transitionend": "_onTransitionEnd($event)", "mouseenter": "_handleMouseEnter()", "mouseleave": "_handleMouseLeave()" }, properties: { "class.ngs-tooltip-visible": "_visibility === 'visible'", "class.ngs-tooltip-hidden": "_visibility === 'hidden'" } }, ngImport: i0, template: `
    <div class="ngs-tooltip"
         [ngClass]="tooltipClass">
      {{message}}
    </div>
  `, isInline: true, styles: [":host{--ngs-tooltip-container-color: var(--ngs-color-neutral-950);--ngs-tooltip-supporting-text-color: var(--ngs-color-neutral-100);--ngs-tooltip-padding: 8px;--ngs-tooltip-border-radius: var(--ngs-radius-md);--ngs-tooltip-font-size: var(--ngs-font-size-xs);--ngs-tooltip-line-height: 16px;--ngs-tooltip-max-width: 200px;--ngs-tooltip-handset-padding: 12px;--ngs-tooltip-handset-font-size: 14px;pointer-events:auto;display:block;padding:var(--ngs-tooltip-padding);border-radius:var(--ngs-tooltip-border-radius);font-size:var(--ngs-tooltip-font-size);line-height:var(--ngs-tooltip-line-height);max-width:var(--ngs-tooltip-max-width);overflow:hidden;text-overflow:ellipsis;background:var(--ngs-tooltip-container-color);color:var(--ngs-tooltip-supporting-text-color);opacity:0;transform:scale(.8);transition:opacity .15s cubic-bezier(0,0,.2,1),transform .15s cubic-bezier(0,0,.2,1)}:host.ngs-tooltip-visible{opacity:1;transform:scale(1)}:host.ngs-tooltip-hidden{opacity:0;transform:scale(.8);transition:opacity 75ms cubic-bezier(.4,0,1,1),transform 75ms cubic-bezier(.4,0,1,1)}:host.ngs-tooltip-handset{padding:var(--ngs-tooltip-handset-padding);font-size:var(--ngs-tooltip-handset-font-size)}:host-context(html.dark){--ngs-tooltip-container-color: var(--ngs-color-neutral-100);--ngs-tooltip-supporting-text-color: var(--ngs-color-neutral-950)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TooltipContent, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-tooltip-content', template: `
    <div class="ngs-tooltip"
         [ngClass]="tooltipClass">
      {{message}}
    </div>
  `, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [NgClass], host: {
                        'aria-hidden': 'true',
                        '(body:click)': 'this._handleBodyClick()',
                        '[class.ngs-tooltip-visible]': "_visibility === 'visible'",
                        '[class.ngs-tooltip-hidden]': "_visibility === 'hidden'",
                        '(transitionend)': '_onTransitionEnd($event)',
                        '(mouseenter)': '_handleMouseEnter()',
                        '(mouseleave)': '_handleMouseLeave()',
                    }, styles: [":host{--ngs-tooltip-container-color: var(--ngs-color-neutral-950);--ngs-tooltip-supporting-text-color: var(--ngs-color-neutral-100);--ngs-tooltip-padding: 8px;--ngs-tooltip-border-radius: var(--ngs-radius-md);--ngs-tooltip-font-size: var(--ngs-font-size-xs);--ngs-tooltip-line-height: 16px;--ngs-tooltip-max-width: 200px;--ngs-tooltip-handset-padding: 12px;--ngs-tooltip-handset-font-size: 14px;pointer-events:auto;display:block;padding:var(--ngs-tooltip-padding);border-radius:var(--ngs-tooltip-border-radius);font-size:var(--ngs-tooltip-font-size);line-height:var(--ngs-tooltip-line-height);max-width:var(--ngs-tooltip-max-width);overflow:hidden;text-overflow:ellipsis;background:var(--ngs-tooltip-container-color);color:var(--ngs-tooltip-supporting-text-color);opacity:0;transform:scale(.8);transition:opacity .15s cubic-bezier(0,0,.2,1),transform .15s cubic-bezier(0,0,.2,1)}:host.ngs-tooltip-visible{opacity:1;transform:scale(1)}:host.ngs-tooltip-hidden{opacity:0;transform:scale(.8);transition:opacity 75ms cubic-bezier(.4,0,1,1),transform 75ms cubic-bezier(.4,0,1,1)}:host.ngs-tooltip-handset{padding:var(--ngs-tooltip-handset-padding);font-size:var(--ngs-tooltip-handset-font-size)}:host-context(html.dark){--ngs-tooltip-container-color: var(--ngs-color-neutral-100);--ngs-tooltip-supporting-text-color: var(--ngs-color-neutral-950)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }] });

const TOOLTIP_DEFAULT_OPTIONS = new InjectionToken('TOOLTIP_DEFAULT_OPTIONS', {
    providedIn: 'root',
    factory: () => ({
        showDelay: 0,
        hideDelay: 0,
        touchendHideDelay: 1500,
        offset: 6,
    }),
});
class Tooltip {
    _overlay = inject(Overlay);
    _elementRef = inject((ElementRef));
    _viewContainerRef = inject(ViewContainerRef);
    _dir = inject(Directionality);
    _defaultOptions = inject(TOOLTIP_DEFAULT_OPTIONS);
    _platformId = inject(PLATFORM_ID);
    _overlayRef = null;
    _tooltipInstance = null;
    _portal = null;
    _destroyed = new Subject();
    _lastPositionAtOrigin = null;
    _isContentHovered = false;
    _hideTimeoutId = null;
    message = input('', { ...(ngDevMode ? { debugName: "message" } : /* istanbul ignore next */ {}), alias: 'ngsTooltip' });
    position = input('below', { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipPosition' });
    tooltipClass = input('', { ...(ngDevMode ? { debugName: "tooltipClass" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipClass' });
    showDelay = input(this._defaultOptions.showDelay, { ...(ngDevMode ? { debugName: "showDelay" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipShowDelay',
        transform: numberAttribute });
    hideDelay = input(this._defaultOptions.hideDelay, { ...(ngDevMode ? { debugName: "hideDelay" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipHideDelay',
        transform: numberAttribute });
    offset = input(this._defaultOptions.offset || 6, { ...(ngDevMode ? { debugName: "offset" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipOffset' });
    positionAtOrigin = input(false, { ...(ngDevMode ? { debugName: "positionAtOrigin" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipPositionAtOrigin',
        transform: (value) => {
            if (typeof value === 'string') {
                return value === '' || value === 'true';
            }
            return !!value;
        } });
    disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), alias: 'ngsTooltipDisabled',
        transform: (value) => {
            if (typeof value === 'string') {
                return value === '' || value === 'true';
            }
            return !!value;
        } });
    constructor() {
        effect(() => {
            const message = this.message();
            if (this._tooltipInstance) {
                this._tooltipInstance.message = message;
            }
        });
        effect(() => {
            const tooltipClass = this.tooltipClass();
            if (this._tooltipInstance) {
                this._tooltipInstance.tooltipClass = tooltipClass;
            }
        });
        effect(() => {
            this.position();
            this.offset();
            if (this._overlayRef) {
                this._updatePosition();
            }
        });
        effect(() => {
            if (this.disabled()) {
                this.hide(0);
            }
        });
    }
    ngOnDestroy() {
        if (this._overlayRef) {
            this._overlayRef.dispose();
            this._tooltipInstance = null;
        }
        this._isContentHovered = false;
        this._destroyed.next();
        this._destroyed.complete();
    }
    show(event, delay = this.showDelay()) {
        if (this._hideTimeoutId) {
            if (isPlatformBrowser(this._platformId)) {
                window.clearTimeout(this._hideTimeoutId);
            }
            else {
                clearTimeout(this._hideTimeoutId);
            }
            this._hideTimeoutId = null;
        }
        if (!this.message() || this.disabled()) {
            return;
        }
        const isVisible = this._tooltipInstance?.isVisible();
        if (event instanceof Event && this.positionAtOrigin()) {
            if (!isVisible) {
                this._lastPositionAtOrigin = this._getOrigin(event);
            }
        }
        if (this._tooltipInstance) {
            if (this.positionAtOrigin() && this._lastPositionAtOrigin && this._overlayRef && !isVisible) {
                const strategy = this._overlayRef.getConfig().positionStrategy;
                strategy.setOrigin(this._lastPositionAtOrigin);
                this._overlayRef.updatePosition();
            }
            this._tooltipInstance.show(delay);
            return;
        }
        const overlayRef = this._createOverlay();
        this._portal = this._portal || new ComponentPortal(TooltipContent, this._viewContainerRef);
        this._tooltipInstance = overlayRef.attach(this._portal).instance;
        this._tooltipInstance.message = this.message();
        this._tooltipInstance.tooltipClass = this.tooltipClass();
        this._tooltipInstance
            .afterHidden()
            .pipe(takeUntil(this._destroyed))
            .subscribe(() => this._detach());
        this._tooltipInstance
            .mouseEntered()
            .pipe(takeUntil(this._destroyed))
            .subscribe(() => {
            this._isContentHovered = true;
            if (this._hideTimeoutId) {
                if (isPlatformBrowser(this._platformId)) {
                    window.clearTimeout(this._hideTimeoutId);
                }
                else {
                    clearTimeout(this._hideTimeoutId);
                }
                this._hideTimeoutId = null;
            }
        });
        this._tooltipInstance
            .mouseLeft()
            .pipe(takeUntil(this._destroyed))
            .subscribe(() => {
            this._isContentHovered = false;
            this.hide();
        });
        this._tooltipInstance.show(delay);
    }
    hide(delay = this.hideDelay()) {
        if (this._isContentHovered) {
            return;
        }
        if (this._hideTimeoutId) {
            if (isPlatformBrowser(this._platformId)) {
                window.clearTimeout(this._hideTimeoutId);
            }
            else {
                clearTimeout(this._hideTimeoutId);
            }
        }
        const handler = () => {
            this._hideTimeoutId = null;
            if (this._isContentHovered) {
                return;
            }
            if (this._tooltipInstance) {
                this._tooltipInstance.hide(delay);
            }
        };
        if (isPlatformBrowser(this._platformId)) {
            this._hideTimeoutId = window.setTimeout(handler, 100);
        }
        else {
            this._hideTimeoutId = setTimeout(handler, 100);
        }
    }
    toggle(event) {
        this._tooltipInstance && this._tooltipInstance.isVisible() ? this.hide() : this.show(event);
    }
    _handleMousedown(event) {
        if (this.positionAtOrigin()) {
            this._lastPositionAtOrigin = this._getOrigin(event);
        }
    }
    _handleTouchstart(event) {
        if (this.positionAtOrigin()) {
            this._lastPositionAtOrigin = this._getOrigin(event);
        }
    }
    _getOrigin(event) {
        if (event instanceof MouseEvent) {
            return { x: event.clientX, y: event.clientY };
        }
        const touch = event.touches[0];
        return { x: touch.clientX, y: touch.clientY };
    }
    _createOverlay() {
        if (this._overlayRef) {
            if (this.positionAtOrigin() && this._lastPositionAtOrigin) {
                const strategy = this._overlayRef.getConfig().positionStrategy;
                strategy.setOrigin(this._lastPositionAtOrigin);
                this._overlayRef.updatePosition();
            }
            else if (!this.positionAtOrigin()) {
                const strategy = this._overlayRef.getConfig().positionStrategy;
                strategy.setOrigin(this._elementRef);
                this._overlayRef.updatePosition();
            }
            return this._overlayRef;
        }
        const scrollStrategy = this._overlay.scrollStrategies.reposition();
        let strategy = this._overlay
            .position()
            .flexibleConnectedTo(this.positionAtOrigin() && this._lastPositionAtOrigin ? this._lastPositionAtOrigin : this._elementRef)
            .withTransformOriginOn('.ngs-tooltip')
            .withFlexibleDimensions(false);
        this._overlayRef = this._overlay.create(new OverlayConfig({
            direction: this._dir,
            positionStrategy: strategy,
            scrollStrategy,
            panelClass: 'ngs-tooltip-panel',
        }));
        this._updatePosition();
        this._overlayRef
            .detachments()
            .pipe(takeUntil(this._destroyed))
            .subscribe(() => this._detach());
        return this._overlayRef;
    }
    _detach() {
        if (this._overlayRef && this._overlayRef.hasAttached()) {
            this._overlayRef.detach();
        }
        this._tooltipInstance = null;
        this._lastPositionAtOrigin = null;
    }
    _updatePosition() {
        const strategy = this._overlayRef.getConfig().positionStrategy;
        const positions = this._getPositions();
        strategy.withPositions(positions);
    }
    _getPositions() {
        const position = this.position();
        const offset = this.offset();
        if (position === 'above') {
            return [
                {
                    originX: 'center',
                    originY: 'top',
                    overlayX: 'center',
                    overlayY: 'bottom',
                    offsetY: -offset,
                },
                {
                    originX: 'center',
                    originY: 'bottom',
                    overlayX: 'center',
                    overlayY: 'top',
                    offsetY: offset,
                },
            ];
        }
        else if (position === 'below') {
            return [
                {
                    originX: 'center',
                    originY: 'bottom',
                    overlayX: 'center',
                    overlayY: 'top',
                    offsetY: offset,
                },
                {
                    originX: 'center',
                    originY: 'top',
                    overlayX: 'center',
                    overlayY: 'bottom',
                    offsetY: -offset,
                },
            ];
        }
        else if (position === 'left' || position === 'before') {
            return [
                {
                    originX: 'start',
                    originY: 'center',
                    overlayX: 'end',
                    overlayY: 'center',
                    offsetX: -offset,
                },
                {
                    originX: 'end',
                    originY: 'center',
                    overlayX: 'start',
                    overlayY: 'center',
                    offsetX: offset,
                },
            ];
        }
        else if (position === 'right' || position === 'after') {
            return [
                {
                    originX: 'end',
                    originY: 'center',
                    overlayX: 'start',
                    overlayY: 'center',
                    offsetX: offset,
                },
                {
                    originX: 'start',
                    originY: 'center',
                    overlayX: 'end',
                    overlayY: 'center',
                    offsetX: -offset,
                },
            ];
        }
        return [
            {
                originX: 'center',
                originY: 'bottom',
                overlayX: 'center',
                overlayY: 'top',
                offsetY: offset,
            },
        ];
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: Tooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.4", type: Tooltip, isStandalone: true, selector: "[ngsTooltip]", inputs: { message: { classPropertyName: "message", publicName: "ngsTooltip", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "ngsTooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, tooltipClass: { classPropertyName: "tooltipClass", publicName: "ngsTooltipClass", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "ngsTooltipShowDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "ngsTooltipHideDelay", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "ngsTooltipOffset", isSignal: true, isRequired: false, transformFunction: null }, positionAtOrigin: { classPropertyName: "positionAtOrigin", publicName: "ngsTooltipPositionAtOrigin", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngsTooltipDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "show($event)", "mouseleave": "hide()", "focus": "show($event)", "blur": "hide()", "mousedown": "_handleMousedown($event)", "touchstart": "_handleTouchstart($event)" } }, exportAs: ["ngsTooltip"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: Tooltip, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsTooltip]',
                    exportAs: 'ngsTooltip',
                    standalone: true,
                    host: {
                        '(mouseenter)': 'show($event)',
                        '(mouseleave)': 'hide()',
                        '(focus)': 'show($event)',
                        '(blur)': 'hide()',
                        '(mousedown)': '_handleMousedown($event)',
                        '(touchstart)': '_handleTouchstart($event)',
                    },
                }]
        }], ctorParameters: () => [], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltip", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipPosition", required: false }] }], tooltipClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipClass", required: false }] }], showDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipShowDelay", required: false }] }], hideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipHideDelay", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipOffset", required: false }] }], positionAtOrigin: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipPositionAtOrigin", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTooltipDisabled", required: false }] }] } });

/**
 * Generated bundle index. Do not edit.
 */

export { TOOLTIP_DEFAULT_OPTIONS, Tooltip };
//# sourceMappingURL=ngstarter-ui-components-tooltip.mjs.map
