import * as i0 from '@angular/core';
import { inject, ElementRef, ChangeDetectorRef, Input, HostBinding, ChangeDetectionStrategy, Component, ViewContainerRef, QueryList, ViewChild, forwardRef, ContentChildren, Injectable } 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-icon-button';
import { EUI_ICON_BUTTON } from '@eui/components/eui-icon-button';
import { takeUntil, startWith } from 'rxjs/operators';
import { Subject, BehaviorSubject } from 'rxjs';

/**
 * @description
 * Individual breadcrumb item component representing a single segment in the breadcrumb navigation path.
 * Provides clickable navigation links with optional icons and automatic relationship management with adjacent items.
 * Supports Angular Router navigation with both internal routes and external URLs.
 * Automatically generates unique IDs when not provided and manages collapsed state for responsive layouts.
 * Used within eui-breadcrumb container for hierarchical navigation display.
 *
 * @usageNotes
 * ```html
 * <eui-breadcrumb>
 *   <!-- Home with icon only -->
 *   <eui-breadcrumb-item
 *     link="/"
 *     iconSvgName="home:outline"
 *     ariaLabel="Home">
 *   </eui-breadcrumb-item>
 *
 *   <!-- Standard item with label -->
 *   <eui-breadcrumb-item
 *     link="/products"
 *     label="Products">
 *   </eui-breadcrumb-item>
 *
 *   <!-- Item with navigation extras -->
 *   <eui-breadcrumb-item
 *     link="/products/search"
 *     label="Search Results"
 *     [navigationExtras]="{ queryParams: { q: 'laptop' } }">
 *   </eui-breadcrumb-item>
 *
 *   <!-- Current page (no link) -->
 *   <eui-breadcrumb-item label="Product Details"></eui-breadcrumb-item>
 * </eui-breadcrumb>
 * ```
 *
 * ### Accessibility
 * - Each item is keyboard accessible with Enter/Space activation
 * - ariaLabel provides screen reader context for icon-only items
 * - Non-linked items (current page) are not focusable
 * - Label text is announced by screen readers
 * - Icon and label combination provides visual and semantic meaning
 *
 * ### Notes
 * - Must be used within eui-breadcrumb parent component
 * - id is auto-generated if not provided
 * - link supports string URLs, Angular Router commands (array), or null for non-clickable items
 * - External URLs (starting with 'http') open in same window
 * - navigationExtras passes options to Angular Router (queryParams, fragment, etc.)
 * - iconSvgName follows EUI icon naming convention
 * - Last item in breadcrumb typically has no link (represents current page)
 * - Label may be truncated in responsive layouts
 * - Previous/next relationships are managed automatically by parent component
 */
class EuiBreadcrumbItemComponent {
    constructor() {
        this.string = 'eui-breadcrumb-item';
        /**
         * ARIA label for the breadcrumb item icon for accessibility.
         * Provides screen reader description of the icon.
         * @default 'Breadcrumb item icon'
         */
        this.ariaLabel = 'Breadcrumb item icon';
        /** 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();
    }
    /**
     * Sets the previous breadcrumb item in the navigation chain.
     * Called internally by parent eui-breadcrumb component to establish item relationships.
     */
    setPrevious(breadcrumbItem) {
        this.previousCrumb = breadcrumbItem;
        this.cdr.detach();
        this.hasPrevious = breadcrumbItem ? true : false;
        this.cdr.detectChanges();
        this.cdr.reattach();
    }
    /**
     * Sets the next breadcrumb item in the navigation chain.
     * Called internally by parent eui-breadcrumb component to establish item relationships.
     */
    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);
            }
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiBreadcrumbItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: EuiBreadcrumbItemComponent, isStandalone: true, selector: "eui-breadcrumb-item", inputs: { id: "id", label: "label", iconSvgName: "iconSvgName", ariaLabel: "ariaLabel", link: "link", navigationExtras: "navigationExtras" }, host: { properties: { "class": "this.string" } }, ngImport: i0, template: "@if (hasPrevious) {\n    <eui-icon-svg icon=\"eui-chevron-right\" size=\"2xs\" fillColor=\"secondary\" class=\"eui-u-mh-4xs\"/>\n}\n@if (hasNext) {\n    @if (link) {\n        @if (iconSvgName) {\n            <eui-icon-button [icon]=\"iconSvgName\" hasOverflowHover euiPrimary euiRounded size=\"xs\" (buttonClick)=\"onClick()\" ariaLabel=\"Dialog close icon\"/>\n        } @else {\n            <a class=\"eui-u-text-link-standalone\" (click)=\"onClick()\">\n                {{ label }}\n            </a>\n        }\n    } @else {\n        {{ label }}\n    }\n} @else {\n    {{ label }}\n}\n", styles: [".eui-21 :host{display:inline-flex;font:var(--eui-f-s);z-index:var(--eui-zi-breadcrumb)}\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", "ariaLabel", "ariaHidden", "focusable", "isLoading", "isInputIcon", "euiStart", "euiEnd"] }, { kind: "component", type: i2.EuiIconButtonComponent, selector: "eui-icon-button", inputs: ["icon", "iconUrl", "fillColor", "size", "ariaLabel", "tabindex", "hasNoPadding", "hasOverflowHover", "hasFocusHoverColor", "hasFocusHoverBg", "euiRounded", "euiDisabled"], outputs: ["buttonClick"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiBreadcrumbItemComponent, decorators: [{
            type: Component,
            args: [{ selector: 'eui-breadcrumb-item', changeDetection: ChangeDetectionStrategy.Default, imports: [
                        RouterModule,
                        PortalModule,
                        ...EUI_ICON,
                        ...EUI_ICON_BUTTON,
                    ], template: "@if (hasPrevious) {\n    <eui-icon-svg icon=\"eui-chevron-right\" size=\"2xs\" fillColor=\"secondary\" class=\"eui-u-mh-4xs\"/>\n}\n@if (hasNext) {\n    @if (link) {\n        @if (iconSvgName) {\n            <eui-icon-button [icon]=\"iconSvgName\" hasOverflowHover euiPrimary euiRounded size=\"xs\" (buttonClick)=\"onClick()\" ariaLabel=\"Dialog close icon\"/>\n        } @else {\n            <a class=\"eui-u-text-link-standalone\" (click)=\"onClick()\">\n                {{ label }}\n            </a>\n        }\n    } @else {\n        {{ label }}\n    }\n} @else {\n    {{ label }}\n}\n", styles: [".eui-21 :host{display:inline-flex;font:var(--eui-f-s);z-index:var(--eui-zi-breadcrumb)}\n"] }]
        }], propDecorators: { string: [{
                type: HostBinding,
                args: ['class']
            }], id: [{
                type: Input
            }], label: [{
                type: Input
            }], iconSvgName: [{
                type: Input
            }], ariaLabel: [{
                type: Input
            }], link: [{
                type: Input
            }], navigationExtras: [{
                type: Input
            }] } });

/**
 * @description
 * `eui-breadcrumb` navigation component displaying hierarchical page location with linked path segments.
 * Automatically manages relationships between `eui-breadcrumb` items for proper navigation flow.
 * Detects and coordinates child EuiBreadcrumbItemComponent instances through content projection.
 * Provides semantic navigation structure with automatic previous/next item linking.
 * Typically used for showing user location within site hierarchy and enabling quick navigation to parent pages.
 *
 * @usageNotes
 * #### Basic breadcrumb navigation
 * ```html
 * <eui-breadcrumb>
 *   <eui-breadcrumb-item link="/" iconSvgName="home:outline" ariaLabel="Home"></eui-breadcrumb-item>
 *   <eui-breadcrumb-item link="/products" label="Products"></eui-breadcrumb-item>
 *   <eui-breadcrumb-item link="/products/electronics" label="Electronics"></eui-breadcrumb-item>
 *   <eui-breadcrumb-item label="Laptops"></eui-breadcrumb-item>
 * </eui-breadcrumb>
 * ```
 *
 * #### With navigation extras
 * ```html
 * <eui-breadcrumb>
 *   <eui-breadcrumb-item link="/" iconSvgName="home:outline"></eui-breadcrumb-item>
 *   <eui-breadcrumb-item
 *     link="/services"
 *     label="Services"
 *     [navigationExtras]="{ queryParams: { page: 1 } }">
 *   </eui-breadcrumb-item>
 * </eui-breadcrumb>
 * ```
 *
 * ### Accessibility
 * - Provides semantic navigation structure for screen readers
 * - Each item is keyboard accessible and focusable
 * - ARIA labels on icons provide context for screen reader users
 * - Current page (last item) is typically not linked
 * - Separators between items are handled automatically
 *
 * ### Notes
 * - Must contain eui-breadcrumb-item children for proper functionality
 * - Automatically establishes previous/next relationships between items
 * - Items are rendered in the order they appear in the template
 * - Last item typically represents current page and should not have a link
 * - Supports responsive behavior with automatic item collapsing
 * - Uses Angular Router for navigation when links are provided
 * - External URLs (starting with 'http') open in same window
 */
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();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", 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: "<ng-container #vcr>\n    <ng-content></ng-content>\n</ng-container>\n", styles: [".eui-21 :host{align-items:center;display:flex;flex-wrap:nowrap;list-style:none;margin:0;padding:var(--eui-s-m) var(--eui-s-m) var(--eui-s-xs) var(--eui-s-m)}@media screen and (max-width:767px){.eui-21 :host{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiBreadcrumbComponent, decorators: [{
            type: Component,
            args: [{ selector: 'eui-breadcrumb', changeDetection: ChangeDetectionStrategy.Default, template: "<ng-container #vcr>\n    <ng-content></ng-content>\n</ng-container>\n", styles: [".eui-21 :host{align-items:center;display:flex;flex-wrap:nowrap;list-style:none;margin:0;padding:var(--eui-s-m) var(--eui-s-m) var(--eui-s-xs) var(--eui-s-m)}@media screen and (max-width:767px){.eui-21 :host{display:none}}\n"] }]
        }], propDecorators: { string: [{
                type: HostBinding,
                args: ['class']
            }], breadcrumbItems: [{
                type: ContentChildren,
                args: [forwardRef(() => EuiBreadcrumbItemComponent), { descendants: false }]
            }], vcr: [{
                type: ViewChild,
                args: ['vcr', { read: ViewContainerRef }]
            }] } });

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;
        }
    }
}

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: "21.2.16", ngImport: i0, type: EuiBreadcrumbService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiBreadcrumbService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: EuiBreadcrumbService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: () => [] });

const EUI_BREADCRUMB = [
    EuiBreadcrumbComponent,
    EuiBreadcrumbItemComponent,
];

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

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