import * as i0 from '@angular/core';
import { InjectionToken, inject, ElementRef, output, input, signal, computed, HostListener, Component, ChangeDetectionStrategy, Injectable, ViewContainerRef, Directive } from '@angular/core';
import { Subject } from 'rxjs';
import { Overlay, FlexibleConnectedPositionStrategy } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { PositionManager } from '@ngstarter-ui/components/overlay';
import { NgTemplateOutlet, NgClass, CommonModule, DOCUMENT } from '@angular/common';
import { DomSanitizer } from '@angular/platform-browser';
import { Button } from '@ngstarter-ui/components/button';
import { Router } from '@angular/router';

const TOUR_CONFIG = new InjectionToken('TOUR_CONFIG');
function provideTourConfig(config) {
    return {
        provide: TOUR_CONFIG,
        useValue: config
    };
}
var TourState;
(function (TourState) {
    TourState[TourState["OFF"] = 0] = "OFF";
    TourState[TourState["ON"] = 1] = "ON";
    TourState[TourState["PAUSED"] = 2] = "PAUSED";
})(TourState || (TourState = {}));
const TOUR_STEP_COMPONENT = new InjectionToken('TOUR_STEP_COMPONENT');

class TourBackdrop {
    elementRef = inject(ElementRef);
    backdropClick = output();
    animateEnterClass = input(true, ...(ngDevMode ? [{ debugName: "animateEnterClass" }] : /* istanbul ignore next */ []));
    animateLeaveClass = input(false, ...(ngDevMode ? [{ debugName: "animateLeaveClass" }] : /* istanbul ignore next */ []));
    rect = signal({ top: 0, left: 0, width: 0, height: 0 }, ...(ngDevMode ? [{ debugName: "rect" }] : /* istanbul ignore next */ []));
    rx = signal(0, ...(ngDevMode ? [{ debugName: "rx" }] : /* istanbul ignore next */ []));
    padding = signal(0, ...(ngDevMode ? [{ debugName: "padding" }] : /* istanbul ignore next */ []));
    disableInteraction = signal(false, ...(ngDevMode ? [{ debugName: "disableInteraction" }] : /* istanbul ignore next */ []));
    viewBox = signal(`0 0 ${window.innerWidth || 1000} ${window.innerHeight || 1000}`, ...(ngDevMode ? [{ debugName: "viewBox" }] : /* istanbul ignore next */ []));
    isInitial = signal(true, ...(ngDevMode ? [{ debugName: "isInitial" }] : /* istanbul ignore next */ []));
    backdropPath = computed(() => {
        const { top, left, width, height } = this.rect();
        const p = this.padding();
        const radius = this.rx();
        const w = window.innerWidth;
        const h = window.innerHeight;
        const rectTop = top - p;
        const rectLeft = left - p;
        const rectWidth = width + 2 * p;
        const rectHeight = height + 2 * p;
        // Outer rectangle (entire screen)
        const screenPath = `M0,0 H${w} V${h} H0 Z`;
        // Hole (inner contour)
        const holePath = `
      M${rectLeft + radius},${rectTop}
      L${rectLeft + rectWidth - radius},${rectTop}
      A${radius},${radius} 0 0 1 ${rectLeft + rectWidth},${rectTop + radius}
      L${rectLeft + rectWidth},${rectTop + rectHeight - radius}
      A${radius},${radius} 0 0 1 ${rectLeft + rectWidth - radius},${rectTop + rectHeight}
      L${rectLeft + radius},${rectTop + rectHeight}
      A${radius},${radius} 0 0 1 ${rectLeft},${rectTop + rectHeight - radius}
      L${rectLeft},${rectTop + radius}
      A${radius},${radius} 0 0 1 ${rectLeft + radius},${rectTop}
      Z
    `.replace(/\s+/g, ' ');
        return `${screenPath} ${holePath}`;
    }, ...(ngDevMode ? [{ debugName: "backdropPath" }] : /* istanbul ignore next */ []));
    constructor() {
        this.updateViewBox();
    }
    onResize() {
        this.updatePositionFromAnchor();
        this.updateViewBox();
    }
    anchorElement = null;
    updatePosition(rect, borderRadius, anchorElement, padding = 0, disableInteraction = false) {
        if (anchorElement) {
            this.anchorElement = anchorElement;
        }
        const isInitial = this.isInitial();
        this.rect.set({
            top: rect.top,
            left: rect.left,
            width: rect.width,
            height: rect.height
        });
        const radius = parseInt(borderRadius, 10) || 0;
        this.rx.set(radius);
        this.padding.set(padding);
        this.disableInteraction.set(disableInteraction);
        this.updateViewBox();
        if (isInitial) {
            setTimeout(() => {
                this.isInitial.set(false);
            });
        }
    }
    updatePositionFromAnchor() {
        if (this.anchorElement) {
            const rect = this.anchorElement.getBoundingClientRect();
            this.rect.set({
                top: rect.top,
                left: rect.left,
                width: rect.width,
                height: rect.height
            });
        }
    }
    updateViewBox() {
        const w = window.innerWidth || 1000;
        const h = window.innerHeight || 1000;
        this.viewBox.set(`0 0 ${w} ${h}`);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourBackdrop, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: TourBackdrop, isStandalone: true, selector: "ngs-tour-backdrop", inputs: { animateEnterClass: { classPropertyName: "animateEnterClass", publicName: "animateEnterClass", isSignal: true, isRequired: false, transformFunction: null }, animateLeaveClass: { classPropertyName: "animateLeaveClass", publicName: "animateLeaveClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { backdropClick: "backdropClick" }, host: { listeners: { "window:resize": "onResize()", "window:scroll": "onResize()" }, properties: { "class.is-initial": "isInitial()", "class.animate-enter": "animateEnterClass()", "class.animate-leave": "animateLeaveClass()", "style.pointer-events": "\"none\"" } }, ngImport: i0, template: "<svg\n  class=\"absolute top-0 left-0 w-full h-full pointer-events-none\"\n  [attr.viewBox]=\"viewBox()\"\n  preserveAspectRatio=\"xMinYMin slice\"\n>\n  <path\n    fill-rule=\"evenodd\"\n    [attr.d]=\"backdropPath()\"\n    (click)=\"backdropClick.emit()\"\n  />\n  <rect\n    [attr.x]=\"rect().left - padding()\"\n    [attr.y]=\"rect().top - padding()\"\n    [attr.width]=\"rect().width + 2 * padding()\"\n    [attr.height]=\"rect().height + 2 * padding()\"\n    [attr.rx]=\"rx()\"\n    [class.interactive]=\"!disableInteraction()\"\n  ></rect>\n</svg>\n", styles: [":host{position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:1100;display:block;background:transparent;overflow:hidden;visibility:visible}:host path{fill:var(--ngs-overlay-backdrop-bg);pointer-events:auto;cursor:default}:host rect{fill:transparent;stroke:var(--ngs-color-primary);stroke-width:2;pointer-events:auto}:host rect:not(.interactive){pointer-events:none}:host path,:host rect{transition:all .3s cubic-bezier(.4,0,.2,1)}:host.animate-enter{animation:backdrop-fade-in .2s ease-out forwards}:host.animate-leave{animation:backdrop-fade-out .15s ease-in forwards}@keyframes backdrop-fade-in{0%{opacity:0}to{opacity:1}}@keyframes backdrop-fade-out{0%{opacity:1}to{opacity:0}}:host(.is-initial) path,:host(.is-initial) rect{transition:none}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourBackdrop, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-tour-backdrop', standalone: true, host: {
                        '[class.is-initial]': 'isInitial()',
                        '[class.animate-enter]': 'animateEnterClass()',
                        '[class.animate-leave]': 'animateLeaveClass()',
                        '[style.pointer-events]': '"none"',
                    }, template: "<svg\n  class=\"absolute top-0 left-0 w-full h-full pointer-events-none\"\n  [attr.viewBox]=\"viewBox()\"\n  preserveAspectRatio=\"xMinYMin slice\"\n>\n  <path\n    fill-rule=\"evenodd\"\n    [attr.d]=\"backdropPath()\"\n    (click)=\"backdropClick.emit()\"\n  />\n  <rect\n    [attr.x]=\"rect().left - padding()\"\n    [attr.y]=\"rect().top - padding()\"\n    [attr.width]=\"rect().width + 2 * padding()\"\n    [attr.height]=\"rect().height + 2 * padding()\"\n    [attr.rx]=\"rx()\"\n    [class.interactive]=\"!disableInteraction()\"\n  ></rect>\n</svg>\n", styles: [":host{position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:1100;display:block;background:transparent;overflow:hidden;visibility:visible}:host path{fill:var(--ngs-overlay-backdrop-bg);pointer-events:auto;cursor:default}:host rect{fill:transparent;stroke:var(--ngs-color-primary);stroke-width:2;pointer-events:auto}:host rect:not(.interactive){pointer-events:none}:host path,:host rect{transition:all .3s cubic-bezier(.4,0,.2,1)}:host.animate-enter{animation:backdrop-fade-in .2s ease-out forwards}:host.animate-leave{animation:backdrop-fade-out .15s ease-in forwards}@keyframes backdrop-fade-in{0%{opacity:0}to{opacity:1}}@keyframes backdrop-fade-out{0%{opacity:1}to{opacity:0}}:host(.is-initial) path,:host(.is-initial) rect{transition:none}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], ctorParameters: () => [], propDecorators: { backdropClick: [{ type: i0.Output, args: ["backdropClick"] }], animateEnterClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "animateEnterClass", required: false }] }], animateLeaveClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "animateLeaveClass", required: false }] }], onResize: [{
                type: HostListener,
                args: ['window:resize']
            }, {
                type: HostListener,
                args: ['window:scroll']
            }] } });

class TourStep {
    tourService = inject(TourService);
    _sanitizer = inject(DomSanitizer);
    step = input.required(...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
    isFirst = input(false, ...(ngDevMode ? [{ debugName: "isFirst" }] : /* istanbul ignore next */ []));
    isLast = input(false, ...(ngDevMode ? [{ debugName: "isLast" }] : /* istanbul ignore next */ []));
    position = input(null, ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
    animateEnterClass = input(true, ...(ngDevMode ? [{ debugName: "animateEnterClass" }] : /* istanbul ignore next */ []));
    animateLeaveClass = input(false, ...(ngDevMode ? [{ debugName: "animateLeaveClass" }] : /* istanbul ignore next */ []));
    config = inject(TOUR_CONFIG, { optional: true });
    htmlContent = computed(() => {
        const html = this.step().htmlContent;
        return html ? this._sanitizer.bypassSecurityTrustHtml(html) : null;
    }, ...(ngDevMode ? [{ debugName: "htmlContent" }] : /* istanbul ignore next */ []));
    getArrowClasses(pos) {
        if (!pos) {
            return 'hidden';
        }
        const classes = [];
        // Vertical position of the arrow on the step
        if (pos.overlayY === 'top' && pos.originY === 'bottom') {
            classes.push('pos-top'); // Arrow on the top edge of the step
        }
        else if (pos.overlayY === 'bottom' && pos.originY === 'top') {
            classes.push('pos-bottom'); // Arrow on the bottom edge of the step
        }
        else if (pos.overlayX === 'start' && pos.originX === 'end') {
            // Step is to the right of the element (AFTER)
            classes.push('pos-left');
        }
        else if (pos.overlayX === 'end' && pos.originX === 'start') {
            // Step is to the left of the element (BEFORE)
            classes.push('pos-right');
        }
        // Alignment of the arrow on the chosen edge
        if (classes.includes('pos-top') || classes.includes('pos-bottom')) {
            if (pos.overlayX === 'center') {
                classes.push('align-center');
            }
            else if (pos.overlayX === 'start') {
                classes.push('align-start');
            }
            else if (pos.overlayX === 'end') {
                classes.push('align-end');
            }
        }
        else if (classes.includes('pos-left') || classes.includes('pos-right')) {
            if (pos.overlayY === 'center') {
                classes.push('align-center');
            }
            else if (pos.overlayY === 'top') {
                classes.push('align-start');
            }
            else if (pos.overlayY === 'bottom') {
                classes.push('align-end');
            }
        }
        return classes.join(' ');
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourStep, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: TourStep, isStandalone: true, selector: "ngs-tour-step", inputs: { step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: true, transformFunction: null }, isFirst: { classPropertyName: "isFirst", publicName: "isFirst", isSignal: true, isRequired: false, transformFunction: null }, isLast: { classPropertyName: "isLast", publicName: "isLast", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, animateEnterClass: { classPropertyName: "animateEnterClass", publicName: "animateEnterClass", isSignal: true, isRequired: false, transformFunction: null }, animateLeaveClass: { classPropertyName: "animateLeaveClass", publicName: "animateLeaveClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.animate-enter": "animateEnterClass()", "class.animate-leave": "animateLeaveClass()" }, classAttribute: "ngs-tour-step not-prose" }, ngImport: i0, template: "@if (!step().hideArrow) {\n  <div class=\"tour-step-arrow\" [ngClass]=\"getArrowClasses(position())\"></div>\n}\n<div class=\"relative z-[1] transform-gpu\">\n  @if (step().title) {\n    <h3 class=\"mt-0 mb-2 font-semibold text-base leading-none tracking-tight\">{{ step().title }}</h3>\n  }\n\n  <div class=\"text-sm text-on-surface-variant\">\n    @if (step().template) {\n      <ng-container *ngTemplateOutlet=\"step().template!; context: step().templateContext\"/>\n    } @else if (htmlContent()) {\n      <div [innerHTML]=\"htmlContent()\"></div>\n    } @else {\n      {{ step().content }}\n    }\n  </div>\n\n  <div class=\"flex justify-between gap-4 mt-4\">\n    <button ngsButton (click)=\"tourService.end()\" class=\"button\">\n      {{ step().skipBtnText || config?.skipBtnText || 'Close' }}\n    </button>\n    <div class=\"flex gap-2\">\n      <button ngsButton=\"tonal\" (click)=\"tourService.prev()\" [disabled]=\"isFirst()\" class=\"button\">\n        {{ step().prevBtnText || config?.prevBtnText || 'Prev' }}\n      </button>\n      <button ngsButton=\"filled\" (click)=\"tourService.next()\" class=\"button\">\n        @if (isLast()) {\n          {{ step().finishBtnText || config?.finishBtnText || 'Finish' }}\n        } @else {\n          {{ step().nextBtnText || config?.nextBtnText || 'Next' }}\n        }\n      </button>\n    </div>\n  </div>\n</div>\n", styles: [":host{--ngs-guided-tour-step-bg: var(--ngs-color-surface-container-lowest);--ngs-guided-tour-step-border: 1px solid var(--ngs-color-subtle);--ngs-guided-tour-arrow-border-color: var(--ngs-color-subtle);display:block;z-index:1200;position:relative;background:var(--ngs-guided-tour-step-bg);border-radius:var(--ngs-guided-tour-step-radius, var(--ngs-radius-xl));box-shadow:var(--ngs-guided-tour-step-shadow, var(--ngs-shadow-lg));max-width:var(--ngs-guided-tour-step-max-width, 400px);padding:var(--ngs-guided-tour-step-step-padding, calc(var(--spacing, .25rem) * 4));border:var(--ngs-guided-tour-step-border);overflow:visible}:host .button{--ngs-button-height: calc(var(--spacing, .25rem) * 8);--ngs-button-padding: 0 calc(var(--spacing, .25rem) * 3)}:host.animate-enter{animation:step-enter .3s cubic-bezier(.4,0,.2,1) forwards}:host.animate-leave{animation:step-leave .15s cubic-bezier(.4,0,.2,1) forwards}:host .tour-step-arrow{position:absolute;width:12px;height:12px;background:var(--ngs-guided-tour-step-bg);z-index:10;pointer-events:none;border:1px solid transparent}:host .tour-step-arrow.hidden{display:none}:host .tour-step-arrow.pos-top{top:0;border-top-color:var(--ngs-guided-tour-arrow-border-color);border-left-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-top.align-center{left:50%;transform:translate(-50%) translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-top.align-start{left:16px;transform:translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-top.align-end{right:16px;transform:translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-bottom{bottom:0;border-bottom-color:var(--ngs-guided-tour-arrow-border-color);border-right-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-bottom.align-center{left:50%;transform:translate(-50%) translateY(50%) rotate(45deg)}:host .tour-step-arrow.pos-bottom.align-start{left:16px;transform:translateY(50%) rotate(45deg)}:host .tour-step-arrow.pos-bottom.align-end{right:16px;transform:translateY(50%) rotate(45deg)}:host .tour-step-arrow.pos-left{left:0;border-bottom-color:var(--ngs-guided-tour-arrow-border-color);border-left-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-left.align-center{top:50%;transform:translate(-50%) translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-left.align-start{top:16px;transform:translate(-50%) rotate(45deg)}:host .tour-step-arrow.pos-left.align-end{bottom:16px;transform:translate(-50%) rotate(45deg)}:host .tour-step-arrow.pos-right{right:0;border-top-color:var(--ngs-guided-tour-arrow-border-color);border-right-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-right.align-center{top:50%;transform:translate(50%) translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-right.align-start{top:16px;transform:translate(50%) rotate(45deg)}:host .tour-step-arrow.pos-right.align-end{bottom:16px;transform:translate(50%) rotate(45deg)}@keyframes step-enter{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes step-leave{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "    button[ngsButton], button[ngsIconButton],    a[ngsButton], a[ngsIconButton]  ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourStep, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-tour-step', standalone: true, imports: [
                        NgTemplateOutlet,
                        NgClass,
                        CommonModule,
                        Button
                    ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        'class': 'ngs-tour-step not-prose',
                        '[class.animate-enter]': 'animateEnterClass()',
                        '[class.animate-leave]': 'animateLeaveClass()',
                    }, template: "@if (!step().hideArrow) {\n  <div class=\"tour-step-arrow\" [ngClass]=\"getArrowClasses(position())\"></div>\n}\n<div class=\"relative z-[1] transform-gpu\">\n  @if (step().title) {\n    <h3 class=\"mt-0 mb-2 font-semibold text-base leading-none tracking-tight\">{{ step().title }}</h3>\n  }\n\n  <div class=\"text-sm text-on-surface-variant\">\n    @if (step().template) {\n      <ng-container *ngTemplateOutlet=\"step().template!; context: step().templateContext\"/>\n    } @else if (htmlContent()) {\n      <div [innerHTML]=\"htmlContent()\"></div>\n    } @else {\n      {{ step().content }}\n    }\n  </div>\n\n  <div class=\"flex justify-between gap-4 mt-4\">\n    <button ngsButton (click)=\"tourService.end()\" class=\"button\">\n      {{ step().skipBtnText || config?.skipBtnText || 'Close' }}\n    </button>\n    <div class=\"flex gap-2\">\n      <button ngsButton=\"tonal\" (click)=\"tourService.prev()\" [disabled]=\"isFirst()\" class=\"button\">\n        {{ step().prevBtnText || config?.prevBtnText || 'Prev' }}\n      </button>\n      <button ngsButton=\"filled\" (click)=\"tourService.next()\" class=\"button\">\n        @if (isLast()) {\n          {{ step().finishBtnText || config?.finishBtnText || 'Finish' }}\n        } @else {\n          {{ step().nextBtnText || config?.nextBtnText || 'Next' }}\n        }\n      </button>\n    </div>\n  </div>\n</div>\n", styles: [":host{--ngs-guided-tour-step-bg: var(--ngs-color-surface-container-lowest);--ngs-guided-tour-step-border: 1px solid var(--ngs-color-subtle);--ngs-guided-tour-arrow-border-color: var(--ngs-color-subtle);display:block;z-index:1200;position:relative;background:var(--ngs-guided-tour-step-bg);border-radius:var(--ngs-guided-tour-step-radius, var(--ngs-radius-xl));box-shadow:var(--ngs-guided-tour-step-shadow, var(--ngs-shadow-lg));max-width:var(--ngs-guided-tour-step-max-width, 400px);padding:var(--ngs-guided-tour-step-step-padding, calc(var(--spacing, .25rem) * 4));border:var(--ngs-guided-tour-step-border);overflow:visible}:host .button{--ngs-button-height: calc(var(--spacing, .25rem) * 8);--ngs-button-padding: 0 calc(var(--spacing, .25rem) * 3)}:host.animate-enter{animation:step-enter .3s cubic-bezier(.4,0,.2,1) forwards}:host.animate-leave{animation:step-leave .15s cubic-bezier(.4,0,.2,1) forwards}:host .tour-step-arrow{position:absolute;width:12px;height:12px;background:var(--ngs-guided-tour-step-bg);z-index:10;pointer-events:none;border:1px solid transparent}:host .tour-step-arrow.hidden{display:none}:host .tour-step-arrow.pos-top{top:0;border-top-color:var(--ngs-guided-tour-arrow-border-color);border-left-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-top.align-center{left:50%;transform:translate(-50%) translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-top.align-start{left:16px;transform:translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-top.align-end{right:16px;transform:translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-bottom{bottom:0;border-bottom-color:var(--ngs-guided-tour-arrow-border-color);border-right-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-bottom.align-center{left:50%;transform:translate(-50%) translateY(50%) rotate(45deg)}:host .tour-step-arrow.pos-bottom.align-start{left:16px;transform:translateY(50%) rotate(45deg)}:host .tour-step-arrow.pos-bottom.align-end{right:16px;transform:translateY(50%) rotate(45deg)}:host .tour-step-arrow.pos-left{left:0;border-bottom-color:var(--ngs-guided-tour-arrow-border-color);border-left-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-left.align-center{top:50%;transform:translate(-50%) translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-left.align-start{top:16px;transform:translate(-50%) rotate(45deg)}:host .tour-step-arrow.pos-left.align-end{bottom:16px;transform:translate(-50%) rotate(45deg)}:host .tour-step-arrow.pos-right{right:0;border-top-color:var(--ngs-guided-tour-arrow-border-color);border-right-color:var(--ngs-guided-tour-arrow-border-color)}:host .tour-step-arrow.pos-right.align-center{top:50%;transform:translate(50%) translateY(-50%) rotate(45deg)}:host .tour-step-arrow.pos-right.align-start{top:16px;transform:translate(50%) rotate(45deg)}:host .tour-step-arrow.pos-right.align-end{bottom:16px;transform:translate(50%) rotate(45deg)}@keyframes step-enter{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes step-leave{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.95)}}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], propDecorators: { step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: true }] }], isFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFirst", required: false }] }], isLast: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLast", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], animateEnterClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "animateEnterClass", required: false }] }], animateLeaveClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "animateLeaveClass", required: false }] }] } });

class TourService {
    overlay = inject(Overlay);
    config = inject(TOUR_CONFIG, { optional: true });
    document = inject(DOCUMENT);
    router = inject(Router);
    backdropOverlayRef = null;
    backdropComponentRef = null;
    _steps = signal([], ...(ngDevMode ? [{ debugName: "_steps" }] : /* istanbul ignore next */ []));
    _currentStepIndex = signal(-1, ...(ngDevMode ? [{ debugName: "_currentStepIndex" }] : /* istanbul ignore next */ []));
    _state = signal(TourState.OFF, ...(ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []));
    _anchors = new Map();
    stepOverlayRef = null;
    stepComponentRef = null;
    customStepComponent = inject(TOUR_STEP_COMPONENT, { optional: true });
    constructor() {
        this.document.addEventListener('keydown', this.handleKeyDown);
    }
    ngOnDestroy() {
        this.document.removeEventListener('keydown', this.handleKeyDown);
    }
    handleKeyDown = (event) => {
        if (this.state() !== TourState.ON || this.config?.keyboardNavigation === false) {
            return;
        }
        switch (event.key) {
            case 'ArrowRight':
                void this.next();
                break;
            case 'ArrowLeft':
                void this.prev();
                break;
            case 'Escape':
                void this.end();
                break;
        }
    };
    steps = this._steps.asReadonly();
    currentStepIndex = this._currentStepIndex.asReadonly();
    state = this._state.asReadonly();
    currentStep = computed(() => {
        const index = this._currentStepIndex();
        const steps = this._steps();
        return index >= 0 && index < steps.length ? steps[index] : null;
    }, ...(ngDevMode ? [{ debugName: "currentStep" }] : /* istanbul ignore next */ []));
    stepShow$ = new Subject();
    stepHide$ = new Subject();
    start$ = new Subject();
    end$ = new Subject();
    registerAnchor(id, anchor) {
        this._anchors.set(id, anchor);
    }
    unregisterAnchor(id) {
        this._anchors.delete(id);
    }
    start(steps) {
        this._steps.set(steps);
        this._state.set(TourState.ON);
        this.start$.next();
        void this.goToStep(0);
    }
    async end() {
        const currentStep = this.currentStep();
        if (currentStep) {
            if (currentStep.onHide) {
                await currentStep.onHide();
            }
            this.stepHide$.next(currentStep);
            // Start hiding step and backdrop in parallel
            const hideStepPromise = this._hideStep(currentStep);
            const hideBackdropPromise = this.hideBackdrop(true);
            await Promise.all([hideStepPromise, hideBackdropPromise]);
        }
        else {
            await this.hideBackdrop(true);
        }
        this._state.set(TourState.OFF);
        this._currentStepIndex.set(-1);
        this._steps.set([]);
        this.end$.next();
    }
    async next() {
        const currentStep = this.currentStep();
        if (currentStep?.onNext) {
            await currentStep.onNext();
        }
        if (this._currentStepIndex() < this._steps().length - 1) {
            await this.goToStep(this._currentStepIndex() + 1);
        }
        else {
            await this.end();
        }
    }
    async prev() {
        const currentStep = this.currentStep();
        if (currentStep?.onPrev) {
            await currentStep.onPrev();
        }
        if (this._currentStepIndex() > 0) {
            await this.goToStep(this._currentStepIndex() - 1);
        }
    }
    async goToStep(index) {
        const currentStep = this.currentStep();
        const nextStep = this._steps()[index];
        if (currentStep) {
            if (currentStep.onHide) {
                await currentStep.onHide();
            }
            this.stepHide$.next(currentStep);
            await this._hideStep(currentStep);
        }
        if (currentStep?.withBackdrop && !nextStep?.withBackdrop) {
            this.hideBackdrop(false);
        }
        if (nextStep?.route) {
            const currentUrl = this.router.url;
            const targetUrl = nextStep.route;
            // Compare only path without params and fragment if needed,
            // but usually Router.url returns full path.
            // If URL differs, perform transition.
            if (currentUrl !== targetUrl) {
                await this.router.navigateByUrl(targetUrl);
            }
        }
        if (nextStep?.onShow) {
            await nextStep.onShow();
        }
        if (nextStep?.waitFor) {
            try {
                await this.waitForElement(nextStep.waitFor);
            }
            catch (e) {
                console.warn(`TourService: Element "${nextStep.waitFor}" not found after timeout.`);
            }
        }
        this._currentStepIndex.set(index);
        if (nextStep) {
            this.stepShow$.next(nextStep);
            this._showStep(nextStep);
        }
    }
    waitForElement(selector, timeout = 3000) {
        return new Promise((resolve, reject) => {
            const element = document.querySelector(selector);
            if (element) {
                return resolve(element);
            }
            const observer = new MutationObserver(() => {
                const element = document.querySelector(selector);
                if (element) {
                    observer.disconnect();
                    clearTimeout(timer);
                    resolve(element);
                }
            });
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
            const timer = setTimeout(() => {
                observer.disconnect();
                reject(new Error(`Timeout waiting for element: ${selector}`));
            }, timeout);
        });
    }
    showBackdrop(rect, borderRadius, viewContainerRef, anchorElement, padding = 0, disableInteraction = false) {
        if (!this.backdropOverlayRef) {
            this.backdropOverlayRef = this.overlay.create({
                positionStrategy: this.overlay.position().global(),
                scrollStrategy: this.overlay.scrollStrategies.block(),
                hasBackdrop: false
            });
            const portal = new ComponentPortal(TourBackdrop, viewContainerRef);
            this.backdropComponentRef = this.backdropOverlayRef.attach(portal);
            this.backdropComponentRef.instance.backdropClick.subscribe(() => {
                const step = this.currentStep();
                const closeOnBackdropClick = step?.closeOnBackdropClick ?? this.config?.closeOnBackdropClick ?? false;
                if (closeOnBackdropClick) {
                    this.end();
                }
            });
        }
        this.backdropComponentRef?.instance.updatePosition(rect, borderRadius, anchorElement, padding, disableInteraction);
    }
    async hideBackdrop(animate) {
        const overlayRef = this.backdropOverlayRef;
        const componentRef = this.backdropComponentRef;
        if (!overlayRef) {
            return;
        }
        if (this.backdropOverlayRef === overlayRef) {
            this.backdropOverlayRef = null;
            this.backdropComponentRef = null;
        }
        if (animate) {
            if (componentRef) {
                const safeSetInput = (name, value) => {
                    try {
                        componentRef.setInput(name, value);
                    }
                    catch (e) {
                        // Ignore if input is not declared
                    }
                };
                safeSetInput('animateEnterClass', false);
                safeSetInput('animateLeaveClass', true);
            }
            return new Promise(resolve => {
                setTimeout(() => {
                    overlayRef.dispose();
                    resolve();
                }, 150);
            });
        }
        else {
            overlayRef.dispose();
            return Promise.resolve();
        }
    }
    _showStep(step) {
        const anchorId = typeof step.anchorId === 'function' ? step.anchorId() : step.anchorId;
        let anchorElement = null;
        let anchorDirective = null;
        if (typeof anchorId === 'string') {
            anchorDirective = this._anchors.get(anchorId);
            if (anchorDirective) {
                anchorDirective.showStep(step);
                return;
            }
            anchorElement = document.querySelector(anchorId);
            if (!anchorElement) {
                anchorElement = document.getElementById(anchorId);
            }
        }
        else if (anchorId instanceof HTMLElement) {
            anchorElement = anchorId;
        }
        if (anchorElement) {
            this.showStepForElement(anchorElement, step);
        }
    }
    showStepForElement(element, step) {
        if (this.stepOverlayRef) {
            const oldOverlayRef = this.stepOverlayRef;
            const oldComponentRef = this.stepComponentRef;
            this.stepOverlayRef = null;
            this.stepComponentRef = null;
            oldOverlayRef.dispose();
        }
        const rect = element.getBoundingClientRect();
        const isVisible = (rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth));
        if (!isVisible) {
            element.scrollIntoView({
                behavior: 'instant',
                block: 'center',
                inline: 'nearest'
            });
        }
        setTimeout(() => {
            if (this.state() === TourState.OFF) {
                return;
            }
            const rect = element.getBoundingClientRect();
            const style = window.getComputedStyle(element);
            const padding = step.padding ?? this.config?.padding ?? 4;
            let positionStrategy;
            const positionManager = new PositionManager();
            const defaultPositions = [
                ...positionManager.build('below-center'),
                ...positionManager.build('above-center'),
                ...positionManager.build('after-center'),
                ...positionManager.build('before-center'),
            ].map(p => ({ ...p, ...this._getOffset(p, padding) }));
            const preferredPositions = step.position
                ? positionManager.build(step.position).map(p => ({ ...p, ...this._getOffset(p, padding) }))
                : defaultPositions;
            positionStrategy = this.overlay
                .position()
                .flexibleConnectedTo(element)
                .withPush(false)
                .withPositions(preferredPositions);
            this.stepOverlayRef = this.overlay.create({
                positionStrategy,
                scrollStrategy: this.overlay.scrollStrategies.block(),
                hasBackdrop: false,
                panelClass: 'ngs-tour-step-overlay'
            });
            if (step.withBackdrop) {
                this.showBackdrop(rect, style.borderRadius, undefined, element, padding, step.disableInteraction);
            }
            const componentType = this.customStepComponent || TourStep;
            const portal = new ComponentPortal(componentType);
            this.stepComponentRef = this.stepOverlayRef.attach(portal);
            const safeSetInput = (name, value) => {
                try {
                    this.stepComponentRef?.setInput(name, value);
                }
                catch (e) {
                    // Ignore if input is not declared
                }
            };
            if (positionStrategy instanceof FlexibleConnectedPositionStrategy) {
                positionStrategy.positionChanges.subscribe((change) => {
                    safeSetInput('position', change.connectionPair);
                });
            }
            const steps = this.steps();
            const index = this.currentStepIndex();
            const isFirst = index === 0;
            const isLast = index === steps.length - 1;
            safeSetInput('step', step);
            safeSetInput('isFirst', isFirst);
            safeSetInput('isLast', isLast);
            if (positionStrategy instanceof FlexibleConnectedPositionStrategy) {
                this.stepOverlayRef.updatePosition();
            }
        }, 0);
    }
    _getOffset(position, padding) {
        const offset = 8 + padding;
        if (position.originY === 'bottom' && position.overlayY === 'top') {
            return { offsetY: offset };
        }
        if (position.originY === 'top' && position.overlayY === 'bottom') {
            return { offsetY: -offset };
        }
        if (position.originX === 'end' && position.overlayX === 'start') {
            return { offsetX: offset };
        }
        if (position.originX === 'start' && position.overlayX === 'end') {
            return { offsetX: -offset };
        }
        return {};
    }
    async _hideStep(step) {
        const anchorId = typeof step.anchorId === 'function' ? step.anchorId() : step.anchorId;
        if (typeof anchorId === 'string') {
            const anchor = this._anchors.get(anchorId);
            if (anchor) {
                await anchor.hideStep();
                return;
            }
        }
        const overlayRef = this.stepOverlayRef;
        const componentRef = this.stepComponentRef;
        if (overlayRef) {
            if (this.stepOverlayRef === overlayRef) {
                this.stepOverlayRef = null;
                this.stepComponentRef = null;
            }
            const safeSetInput = (name, value) => {
                try {
                    componentRef?.setInput(name, value);
                }
                catch (e) {
                    // Ignore if input is not declared
                }
            };
            safeSetInput('animateEnterClass', false);
            safeSetInput('animateLeaveClass', true);
            await new Promise(resolve => setTimeout(resolve, 150));
            overlayRef.dispose();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [] });

class TourAnchorDirective {
    anchorId = input.required({ ...(ngDevMode ? { debugName: "anchorId" } : /* istanbul ignore next */ {}), alias: 'ngsTourAnchor' });
    elementRef = inject(ElementRef);
    tourService = inject(TourService);
    overlay = inject(Overlay);
    viewContainerRef = inject(ViewContainerRef);
    customStepComponent = inject(TOUR_STEP_COMPONENT, { optional: true });
    config = inject(TOUR_CONFIG, { optional: true });
    overlayRef = null;
    componentRef = null;
    ngOnInit() {
        this.tourService.registerAnchor(this.anchorId(), this);
    }
    ngOnDestroy() {
        this.tourService.unregisterAnchor(this.anchorId());
        this.hideStep();
    }
    showStep(step) {
        const currentOverlayRef = this.overlayRef;
        const currentComponentRef = this.componentRef;
        if (this.overlayRef === currentOverlayRef) {
            this.overlayRef = null;
            this.componentRef = null;
        }
        if (currentOverlayRef) {
            currentOverlayRef.dispose();
        }
        const rect = this.elementRef.nativeElement.getBoundingClientRect();
        const isVisible = (rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth));
        if (!isVisible) {
            this.elementRef.nativeElement.scrollIntoView({
                behavior: 'instant',
                block: 'center',
                inline: 'nearest'
            });
        }
        const timeout = 0;
        // Give time for scroll to finish before calculating coordinates for the backdrop
        setTimeout(() => {
            if (this.tourService.state() === 0) { // TourState.OFF
                return;
            }
            const rect = this.elementRef.nativeElement.getBoundingClientRect();
            const style = window.getComputedStyle(this.elementRef.nativeElement);
            const padding = step.padding ?? this.config?.padding ?? 4;
            const positionManager = new PositionManager();
            const defaultPositions = [
                ...positionManager.build('below-center'),
                ...positionManager.build('above-center'),
                ...positionManager.build('after-center'),
                ...positionManager.build('before-center'),
            ].map(p => ({ ...p, ...this._getOffset(p, padding) }));
            const preferredPositions = step.position
                ? positionManager.build(step.position).map(p => ({ ...p, ...this._getOffset(p, padding) }))
                : defaultPositions;
            const positionStrategy = this.overlay
                .position()
                .flexibleConnectedTo(this.elementRef)
                .withPush(false)
                .withPositions(preferredPositions);
            this.overlayRef = this.overlay.create({
                positionStrategy,
                scrollStrategy: this.overlay.scrollStrategies.block(),
                hasBackdrop: false,
                panelClass: 'ngs-tour-step-overlay'
            });
            if (step.withBackdrop) {
                this.tourService.showBackdrop(rect, style.borderRadius, this.viewContainerRef, this.elementRef.nativeElement, padding, step.disableInteraction);
            }
            const componentType = this.customStepComponent || TourStep;
            const portal = new ComponentPortal(componentType, this.viewContainerRef);
            this.componentRef = this.overlayRef.attach(portal);
            const safeSetInput = (name, value) => {
                try {
                    this.componentRef?.setInput(name, value);
                }
                catch (e) {
                    // Ignore if input is not declared
                }
            };
            if (positionStrategy instanceof FlexibleConnectedPositionStrategy) {
                positionStrategy.positionChanges.subscribe((change) => {
                    safeSetInput('position', change.connectionPair);
                });
                // Trigger position calculation to emit initial value
                this.overlayRef.updatePosition();
            }
            const steps = this.tourService.steps();
            const index = this.tourService.currentStepIndex();
            const isFirst = index === 0;
            const isLast = index === steps.length - 1;
            safeSetInput('step', step);
            safeSetInput('isFirst', isFirst);
            safeSetInput('isLast', isLast);
        }, timeout);
    }
    async hideStep() {
        const overlayRef = this.overlayRef;
        const componentRef = this.componentRef;
        if (this.overlayRef === overlayRef) {
            this.overlayRef = null;
            this.componentRef = null;
        }
        if (overlayRef) {
            const safeSetInput = (name, value) => {
                try {
                    componentRef?.setInput(name, value);
                }
                catch (e) {
                    // Ignore if input is not declared
                }
            };
            safeSetInput('animateEnterClass', false);
            safeSetInput('animateLeaveClass', true);
            await new Promise(resolve => setTimeout(resolve, 200));
            overlayRef.dispose();
        }
    }
    _getOffset(position, padding) {
        const offset = 8 + padding;
        if (position.originY === 'bottom' && position.overlayY === 'top') {
            return { offsetY: offset };
        }
        if (position.originY === 'top' && position.overlayY === 'bottom') {
            return { offsetY: -offset };
        }
        if (position.originX === 'end' && position.overlayX === 'start') {
            return { offsetX: offset };
        }
        if (position.originX === 'start' && position.overlayX === 'end') {
            return { offsetX: -offset };
        }
        return {};
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourAnchorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.4", type: TourAnchorDirective, isStandalone: true, selector: "[ngsTourAnchor]", inputs: { anchorId: { classPropertyName: "anchorId", publicName: "ngsTourAnchor", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: TourAnchorDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsTourAnchor]',
                    standalone: true
                }]
        }], propDecorators: { anchorId: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngsTourAnchor", required: true }] }] } });

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

export { TOUR_CONFIG, TOUR_STEP_COMPONENT, TourAnchorDirective, TourService, TourState, TourStep, provideTourConfig };
//# sourceMappingURL=ngstarter-ui-components-guided-tour.mjs.map
