import * as i0 from '@angular/core';
import { inject, ElementRef, ChangeDetectorRef, Input, HostBinding, ViewEncapsulation, ChangeDetectionStrategy, Component, ViewContainerRef, QueryList, ComponentRef, ViewChild, forwardRef, ContentChildren, Injectable, NgModule } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { injectOptional, LogService } from '@eui/core';
import { PortalModule } from '@angular/cdk/portal';
import * as i1 from '@eui/components/eui-icon';
import { EUI_ICON } from '@eui/components/eui-icon';
import * as i2 from '@eui/components/eui-label';
import { EUI_LABEL } from '@eui/components/eui-label';
import { takeUntil, startWith } from 'rxjs/operators';
import { Subject, BehaviorSubject } from 'rxjs';

class EuiBreadcrumbItemComponent {
    constructor() {
        this.string = 'eui-breadcrumb-item';
        /** calculated item width */
        this.width = 0;
        this.hasPrevious = false;
        this.hasNext = false;
        /** state of breadcrumb item in case of collapsed */
        this.collapsed = false;
        this.elementRef = inject(ElementRef);
        this.host = inject(ElementRef);
        this.router = inject(Router);
        this.cdr = inject(ChangeDetectorRef);
        this.logService = injectOptional(LogService);
    }
    ngOnInit() {
        // generate a random ID if none exists
        if (!this.id) {
            this.id = Math.trunc(Math.random() * 1000).toString();
        }
    }
    ngOnDestroy() {
        if (this.logService) {
            this.logService.info(`Crumb with id:${this.id} destroyed`);
        }
    }
    destroy() {
        this.host.nativeElement.remove();
    }
    /**
     * set the previous breadcrumb item
     *
     * @param  breadcrumbItem The previous item to point to.
     */
    setPrevious(breadcrumbItem) {
        this.previousCrumb = breadcrumbItem;
        this.cdr.detach();
        this.hasPrevious = breadcrumbItem ? true : false;
        this.cdr.detectChanges();
        this.cdr.reattach();
    }
    /**
     * set the next breadcrumb item
     *
     * @param breadcrumbItem The next item to point to.
     */
    setNext(breadcrumbItem) {
        this.nextCrumb = breadcrumbItem;
        this.cdr.detach();
        this.hasNext = breadcrumbItem ? true : false;
        this.cdr.detectChanges();
        this.cdr.reattach();
    }
    /**
     * A callback to navigate to the given link using ng-router.
     *
     * @param event
     */
    onClick() {
        if (this.link) {
            if (typeof this.link === 'string') {
                if (this.link.startsWith('http')) {
                    window.location.href = this.link;
                    return true;
                }
                const extra = this.navigationExtras || { skipLocationChange: false };
                this.router.navigateByUrl(this.link, extra);
            }
            else {
                this.router.navigate(this.link, this.navigationExtras);
            }
        }
    }
    /**
     * get the next breadcrumb item
     */
    getNext() {
        return this.nextCrumb;
    }
    /**
     * get the previous breadcrumb item
     */
    getPrevious() {
        return this.previousCrumb;
    }
    rendererIconBefore() {
        return this.previousCrumb !== undefined;
    }
    isLast() {
        return !this.nextCrumb;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: EuiBreadcrumbItemComponent, isStandalone: true, selector: "eui-breadcrumb-item", inputs: { id: "id", label: "label", link: "link", navigationExtras: "navigationExtras" }, host: { properties: { "class": "this.string" } }, ngImport: i0, template: "@if (hasPrevious) {\n    <div class=\"eui-breadcrumb-item__separator\">\n        <eui-icon-svg icon=\"chevron-forward:sharp\" size=\"xs\" fillColor=\"neutral\"></eui-icon-svg>\n    </div>\n}\n@if (hasNext) {\n    @if (link) {\n        <a class=\"eui-breadcrumb-item__label-wrapper eui-u-text-link-standalone\" href=\"javascript:void(0)\" (click)=\"onClick()\">\n            <span class=\"eui-breadcrumb-item__label\">{{ label }}</span>\n        </a>\n    } @else {\n        <span class=\"eui-breadcrumb-item__label-wrapper\" euiLabel euiSecondary>\n            <span class=\"eui-breadcrumb-item__label\">{{ label }}</span>\n        </span>\n    }\n} @else {\n    <span class=\"eui-breadcrumb-item__label-wrapper\" euiLabel euiSecondary>\n        <span class=\"eui-breadcrumb-item__label\">{{ label }}</span>\n    </span>\n}\n", dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: PortalModule }, { kind: "component", type: i1.EuiIconSvgComponent, selector: "eui-icon-svg, span[euiIconSvg], i[euiIconSvg]", inputs: ["icon", "fillColor", "set", "size", "style", "iconUrl", "transform", "euiVariant", "aria-label", "ariaHidden", "focusable", "isLoading", "isInputIcon", "euiStart", "euiEnd"] }, { kind: "component", type: i2.EuiLabelComponent, selector: "label[euiLabel], span[euiLabel], div[euiLabel], a[euiLabel], eui-label,               label[euiSublabel], span[euiSublabel], div[euiSublabel], a[euiSublabel], eui-sublabel", inputs: ["euiRequired", "euiReadonly", "euiSublabel"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbItemComponent, decorators: [{
            type: Component,
            args: [{ selector: 'eui-breadcrumb-item', changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, imports: [
                        RouterModule,
                        PortalModule,
                        ...EUI_ICON,
                        ...EUI_LABEL,
                    ], template: "@if (hasPrevious) {\n    <div class=\"eui-breadcrumb-item__separator\">\n        <eui-icon-svg icon=\"chevron-forward:sharp\" size=\"xs\" fillColor=\"neutral\"></eui-icon-svg>\n    </div>\n}\n@if (hasNext) {\n    @if (link) {\n        <a class=\"eui-breadcrumb-item__label-wrapper eui-u-text-link-standalone\" href=\"javascript:void(0)\" (click)=\"onClick()\">\n            <span class=\"eui-breadcrumb-item__label\">{{ label }}</span>\n        </a>\n    } @else {\n        <span class=\"eui-breadcrumb-item__label-wrapper\" euiLabel euiSecondary>\n            <span class=\"eui-breadcrumb-item__label\">{{ label }}</span>\n        </span>\n    }\n} @else {\n    <span class=\"eui-breadcrumb-item__label-wrapper\" euiLabel euiSecondary>\n        <span class=\"eui-breadcrumb-item__label\">{{ label }}</span>\n    </span>\n}\n" }]
        }], propDecorators: { string: [{
                type: HostBinding,
                args: ['class']
            }], id: [{
                type: Input
            }], label: [{
                type: Input
            }], link: [{
                type: Input
            }], navigationExtras: [{
                type: Input
            }] } });

/**
 * @description
 * Component that provides a breadcrumb navigation.
 */
class EuiBreadcrumbComponent {
    constructor() {
        this.string = 'eui-breadcrumb';
        this.destroy$ = new Subject();
        /** Observable emitting when the breadcrumb Items List has changed */
        this.breadcrumbItemsListChanged = new Subject();
        this.viewContainerRef = inject(ViewContainerRef);
    }
    ngAfterContentInit() {
        this.breadcrumbItems.changes.pipe(takeUntil(this.destroy$), startWith(true)).subscribe((changes) => {
            if (changes instanceof QueryList) {
                this.breadcrumbItems = changes;
                this.breadcrumbItemsListChanged.next();
            }
            this.breadcrumbItems.forEach((item, index, array) => {
                item.setPrevious(array[index - 1]);
                item.setNext(array[index + 1]);
            });
        });
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.unsubscribe();
    }
    /**
     * Adds a crumb in the chain
     *
     * @param crumb It can either be a Component reference or BreadCrumbItem object
     * @throws Will throw an error if given ID already exists.
     */
    add(crumb) {
        // check if item already exists and throw an error
        const id = crumb?.id || crumb?.instance?.id;
        if (this.breadcrumbItems.find((c) => c.id === id)) {
            throw new Error('This crumb already exists');
        }
        // if crumb is not instance of ComponentRef create the
        // reference using current View Container
        if (!(crumb instanceof ComponentRef)) {
            const crumbRef = this.viewContainerRef.createComponent(EuiBreadcrumbItemComponent);
            crumbRef.instance.id = crumb.id;
            crumbRef.instance.link = crumb.link;
            crumbRef.instance.label = crumb.label;
            crumbRef.instance.navigationExtras = crumb.navigationExtras;
            crumb = crumbRef;
        }
        this.vcr.insert(crumb.hostView);
        this.breadcrumbItems.reset([...this.breadcrumbItems.toArray(), crumb.instance]);
        this.breadcrumbItems.notifyOnChanges();
    }
    /**
     * Removes a crumb from the chain
     *
     * @param crumb Can be either a crumb instance or a crumb ID
     * @throws Will throw an error if given ID is not found.
     */
    remove(crumb) {
        crumb = typeof crumb === 'string' ? crumb : crumb.id;
        const found = this.breadcrumbItems.find((item) => item.id === crumb);
        if (!found) {
            throw new Error(`Given breadcrumb with id ${crumb} not found in order to be removed.`);
        }
        found.destroy();
        this.breadcrumbItems.reset([...this.breadcrumbItems.filter((c) => c.id !== found.id)]);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.17", type: EuiBreadcrumbComponent, isStandalone: true, selector: "eui-breadcrumb", host: { properties: { "class": "this.string" } }, queries: [{ propertyName: "breadcrumbItems", predicate: i0.forwardRef(() => EuiBreadcrumbItemComponent) }], viewQueries: [{ propertyName: "vcr", first: true, predicate: ["vcr"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div class=\"eui-breadcrumb__items\">\n    <ng-container #vcr>\n        <ng-content></ng-content>\n    </ng-container>\n</div>\n", styles: [".eui-19 .eui-breadcrumb{align-items:center;display:flex;width:100%;position:relative}.eui-19 .eui-breadcrumb__items{align-items:center;display:flex;flex-wrap:nowrap;list-style:none;margin:0;padding:var(--eui-s-m) var(--eui-s-m)}@media screen and (max-width: 767px){.eui-19 eui-breadcrumb,.eui-19 .eui-breadcrumb{display:none}}.eui-19 .eui-breadcrumb-item{align-items:center;display:flex;z-index:var(--eui-zi-breadcrumb);font:var(--eui-f-s)}.eui-19 .eui-breadcrumb-item__separator{align-items:center;display:flex;padding:0 var(--eui-s-2xs)}.eui-19 .eui-breadcrumb-item__label-wrapper{padding:0 var(--eui-s-2xs)}\n"], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbComponent, decorators: [{
            type: Component,
            args: [{ selector: 'eui-breadcrumb', changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, template: "<div class=\"eui-breadcrumb__items\">\n    <ng-container #vcr>\n        <ng-content></ng-content>\n    </ng-container>\n</div>\n", styles: [".eui-19 .eui-breadcrumb{align-items:center;display:flex;width:100%;position:relative}.eui-19 .eui-breadcrumb__items{align-items:center;display:flex;flex-wrap:nowrap;list-style:none;margin:0;padding:var(--eui-s-m) var(--eui-s-m)}@media screen and (max-width: 767px){.eui-19 eui-breadcrumb,.eui-19 .eui-breadcrumb{display:none}}.eui-19 .eui-breadcrumb-item{align-items:center;display:flex;z-index:var(--eui-zi-breadcrumb);font:var(--eui-f-s)}.eui-19 .eui-breadcrumb-item__separator{align-items:center;display:flex;padding:0 var(--eui-s-2xs)}.eui-19 .eui-breadcrumb-item__label-wrapper{padding:0 var(--eui-s-2xs)}\n"] }]
        }], propDecorators: { string: [{
                type: HostBinding,
                args: ['class']
            }], breadcrumbItems: [{
                type: ContentChildren,
                args: [forwardRef(() => EuiBreadcrumbItemComponent), { descendants: false }]
            }], vcr: [{
                type: ViewChild,
                args: ['vcr', { read: ViewContainerRef }]
            }] } });

class EuiBreadcrumbService {
    constructor() {
        this.breadcrumb = [];
        this.breadcrumbsSource$ = new BehaviorSubject(this.breadcrumb);
        this.breadcrumbs$ = this.breadcrumbsSource$.asObservable();
    }
    /**
     * Adds a new BreadCrumbItem into the breadcrumb
     *
     * @param breadCrumbItem The BreadCrumbItem you want to insert in trail
     * @param [after] The ID of the BreadCrumbItem after given one will be inserted.
     * @param [removeAfter=false] All crumbs after given ID will be removed.
     * @throws Will throw an error if given after ID is not found on current trail.
     */
    addCrumb(breadCrumbItem, after, removeAfter = false) {
        if (after) {
            // find ID for which provided BreadCrumbItem will be inserted after
            const index = this.breadcrumb.findIndex((item) => item.id === after);
            if (index < 0) {
                throw new Error(`The provided afterId: ${after}, has not been found in current breadcrumb`);
            }
            // in case removeAfter=true then remove all crumbs after given one
            this.breadcrumb.splice(index, removeAfter ? this.breadcrumb.length - index : 0, breadCrumbItem);
        }
        else {
            const index = this.breadcrumb.findIndex((item) => item.id === breadCrumbItem.id);
            if (index !== -1) {
                throw new Error(`The provided id: ${breadCrumbItem.id} is already in current breadcrumb`);
            }
            this.breadcrumb.push(breadCrumbItem);
        }
        // Notify observers
        this.breadcrumbsSource$.next(this.breadcrumb);
    }
    /**
     * Remove a BreadCrumbItem based on a given ID
     *
     * @param id Optional: The ID of BreadCrumbItem to be removed
     *           If no id provided then the last item will be popped.
     */
    removeCrumb(id) {
        if (id) {
            this.breadcrumb = this.breadcrumb.filter((item) => item.id !== id);
        }
        else {
            this.breadcrumb.pop();
        }
        // Notify observers
        this.breadcrumbsSource$.next(this.breadcrumb);
    }
    /**
     * Update a specific entry in the data structure
     *
     * @param BreadCrumbItem The BreadCrumbItem to match and update
     * @throws Will throw an Error if BreadCrumbItem is not part of the breadcrumb
     */
    updateCrumb(item) {
        const index = this.breadcrumb.findIndex((c) => c.id === item.id);
        if (index < 0) {
            throw new Error(`The provided afterId: ${item.id}, has not been found in current breadcrumb`);
        }
        this.breadcrumb.splice(index, 1, item);
        // Notify observers
        this.breadcrumbsSource$.next(this.breadcrumb);
    }
    /**
     * Returns current breadcrumb
     */
    getBreadcrumb() {
        return this.breadcrumb;
    }
    /**
     * Sets the breadcrumb
     */
    setBreadcrumb(breadcrumb) {
        this.breadcrumb = breadcrumb;
        // Notify observers
        this.breadcrumbsSource$.next(this.breadcrumb);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: () => [] });

/**
 * @description
 * Module that provides the EuiBreadcrumb component and its dependencies.
 *
 * @deprecated Use {@link EUI_BREADCRUMB} instead.
 */
class EuiBreadcrumbModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbModule, imports: [EuiBreadcrumbComponent,
            EuiBreadcrumbItemComponent], exports: [EuiBreadcrumbComponent,
            EuiBreadcrumbItemComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbModule, providers: [
            EuiBreadcrumbService,
        ], imports: [EuiBreadcrumbItemComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: EuiBreadcrumbModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        EuiBreadcrumbComponent,
                        EuiBreadcrumbItemComponent,
                    ],
                    providers: [
                        EuiBreadcrumbService,
                    ],
                    exports: [
                        EuiBreadcrumbComponent,
                        EuiBreadcrumbItemComponent,
                    ],
                }]
        }] });

class BreadCrumbItem {
    /** A URL link. Commands to pass to {@link Router#createUrlTree Router#createUrlTree}.
     *   - **array**: commands to pass to {@link Router#createUrlTree Router#createUrlTree}.
     *   - **string**: shorthand for array of commands with just the string, i.e. `['/route']`
     *   - **null|undefined**: Disables the link by removing the `href`
     */
    // TODO: find the correct type or turn into a generic, https://www.typescriptlang.org/docs/handbook/2/generics.html
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    get link() {
        return this._link;
    }
    // TODO: find the correct type or turn into a generic, https://www.typescriptlang.org/docs/handbook/2/generics.html
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    set link(link) {
        if (typeof link === 'string') {
            try {
                let url;
                if (!link.startsWith('http')) {
                    url = new URL(link, 'http://placeholder');
                    this._link = url.pathname;
                }
                else {
                    url = new URL(link);
                    this._link = link;
                }
                if (!this.navigationExtras) {
                    this.navigationExtras = {};
                }
                this.navigationExtras.fragment = url.hash.replace('#', '');
                this.navigationExtras.queryParams = Object.fromEntries(url.search
                    .replace('?', '')
                    .split('&')
                    .map((i) => i.split('=')));
            }
            catch (e) {
                throw new Error('The given link is not a valid URL');
            }
        }
        else {
            this._link = link;
        }
    }
}

const EUI_BREADCRUMB = [
    EuiBreadcrumbComponent,
    EuiBreadcrumbItemComponent,
];

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

export { BreadCrumbItem, EUI_BREADCRUMB, EuiBreadcrumbComponent, EuiBreadcrumbItemComponent, EuiBreadcrumbModule, EuiBreadcrumbService };
//# sourceMappingURL=eui-components-eui-breadcrumb.mjs.map
