import * as i0 from '@angular/core';
import { EventEmitter, QueryList, ChangeDetectorRef, ElementRef, AfterContentInit } from '@angular/core';
import { Subject } from 'rxjs';
import { DefaultMenuItem, MenuKeyboardService } from '@fundamental-ngx/core/menu';
import { Nullable } from '@fundamental-ngx/cdk/utils';
import { IconComponent } from '@fundamental-ngx/core/icon';
import { PopoverComponent } from '@fundamental-ngx/core/popover';
import { Placement } from '@fundamental-ngx/core/shared';
import { ContentDensityObserver } from '@fundamental-ngx/core/content-density';

/** Interface, to reduce amount of circular dependency warnings */
interface NestedItemInterface extends DefaultMenuItem {
    expanded: boolean;
    keyboardTriggered: EventEmitter<KeyboardEvent>;
    triggerOpen: () => void;
    triggerClose: () => void;
    linkItem: NestedItemLink;
    allChildrenItems: NestedItemInterface[];
    hasChildren: boolean;
    containsId: (id: string) => boolean;
}
interface NestedItemLink {
    changeSelected(selected: boolean): void;
    focus(): void;
    click(): void;
    getTitle(): string;
}

/** Interface, to reduce amount of circular dependency warnings */
interface NestedListPopoverInterface {
    parentItemElement: NestedItemInterface;
    open: boolean;
    handleOpenChange: (boolean: any) => void;
}

/** Interface, to reduce amount of circular dependency warnings */
interface NestedListInterface {
    nestedItems: QueryList<NestedItemInterface>;
    hidden: boolean;
    detectChanges: () => void;
}

/** Contains references to popover or list nested components, that are placed as direct children of item component */
declare class NestedItemService {
    /** @hidden */
    list: NestedListInterface;
    /** @hidden */
    popover?: NestedListPopoverInterface;
    /** Subject fired when expand icon is clicked */
    toggle: Subject<boolean>;
    /** Subject fired, when child elements are focused */
    focus: Subject<void>;
    /** Subject fired, when content or link is clicked */
    click: Subject<void>;
    /** KeyDown handler, it is triggered from link, content and item elements */
    keyDown: Subject<KeyboardEvent>;
}

declare class NestedListHeaderDirective {
    /** Id of the element. */
    id: string | null;
    /** @hidden */
    private readonly _elementRef;
    /** Get the header title */
    get title(): string;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListHeaderDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<NestedListHeaderDirective, "[fdNestedDirectivesHeader], [fd-nested-list-header]", never, { "id": { "alias": "id"; "required": false; }; }, {}, never, never, true, never>;
}
declare class NestedListIconComponent extends IconComponent {
    /** Role attribute */
    role: string;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListIconComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<NestedListIconComponent, "[fdNestedDirectivesIcon], [fd-nested-list-icon]", never, { "role": { "alias": "role"; "required": false; }; }, {}, never, ["*"], true, never>;
}
declare class NestedListTitleDirective {
    /** @hidden */
    private readonly _elementRef;
    /** Returns element's InnerText */
    getInnerText(): string;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListTitleDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<NestedListTitleDirective, "[fdNestedDirectivesTitle], [fd-nested-list-title]", never, {}, {}, never, never, true, never>;
}
declare class NestedListExpandIconComponent {
    /**
     * @hidden
     * Attribute controlled by the parent `NestedItemDirective`
     */
    readonly expanded: i0.WritableSignal<boolean>;
    /** @hidden */
    readonly expandIcon: i0.Signal<"navigation-down-arrow" | "navigation-left-arrow" | "navigation-right-arrow">;
    /** @hidden */
    private readonly _itemService;
    /** @hidden */
    private readonly _rtlService;
    /** Mouse event handler */
    onClick(event: MouseEvent): void;
    /** Handler for focus events */
    onFocus(): void;
    /** @hidden */
    changeExpandedState(expanded: boolean): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListExpandIconComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<NestedListExpandIconComponent, "[fdNestedListExpandIcon], [fd-nested-list-expand-icon]", never, {}, {}, never, ["*"], true, never>;
}

declare class NestedLinkDirective implements NestedItemLink {
    changeDetRef: ChangeDetectorRef;
    private _elementRef;
    private _itemService;
    /** Function that is called on click event dispatch on this element. */
    onClickCallback: () => void;
    /** Whether this element is selected*/
    selected: boolean;
    /** @hidden */
    _ariaLabel: string;
    /** @hidden */
    ariaDescribedby: Nullable<string | number>;
    /** Event thrown, when selected state is changed */
    selectedChange: EventEmitter<boolean>;
    /** @hidden */
    fdNestedListItemClass: boolean;
    /** @hidden */
    tabIndex: number;
    /** @hidden */
    role: string;
    /**
     *  @hidden
     *  Reference to title element, it is used, to get title for condensed mode.
     */
    title: NestedListTitleDirective;
    /** @hidden */
    constructor(changeDetRef: ChangeDetectorRef, _elementRef: ElementRef, _itemService: NestedItemService);
    /** Handler for keyboard events */
    onKeyDown(event: KeyboardEvent): void;
    /** Handler for mouse events */
    onClick(): void;
    /** Handler for focus events */
    onFocus(): void;
    /** Method to trigger selected state change */
    changeSelected(selected: boolean): void;
    /** Set focus on the element. */
    focus(): void;
    /** Dispatches the click event on the element */
    click(): void;
    /** Returns the title value of the title directive */
    getTitle(): string;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedLinkDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<NestedLinkDirective, "[fdNestedLink], [fd-nested-list-link]", never, { "onClickCallback": { "alias": "onClickCallback"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "ariaDescribedby": { "alias": "ariaDescribedby"; "required": false; }; }, { "selectedChange": "selectedChange"; }, ["title"], never, true, never>;
}

declare class NestedListContentDirective implements AfterContentInit {
    changeDetRef: ChangeDetectorRef;
    private _elementRef;
    private _itemService;
    /** Whether this element is selected*/
    selected: boolean;
    /** @hidden */
    role: string;
    /** @hidden */
    ariaExpanded: boolean;
    /** Event thrown, when selected state is changed */
    selectedChange: EventEmitter<boolean>;
    /** Event that is thrown, when any keyboard event is dispatched on this element */
    readonly keyboardTriggered: EventEmitter<KeyboardEvent>;
    /** Event that is thrown, when this element is clicked */
    readonly clicked: EventEmitter<MouseEvent>;
    /** @hidden */
    fdNestedListContentClass: boolean;
    /**
     * @hidden
     * Attribute controlled by the parent `NestedItemDirective`
     */
    hasChildren: boolean;
    /** @hidden */
    nestedLink: NestedLinkDirective;
    /** @hidden */
    nestedExpandIcon: NestedListExpandIconComponent;
    /** An RxJS Subject that will kill the data stream upon component’s destruction (for unsubscribing)  */
    private readonly _destroyRef;
    /** @hidden */
    constructor(changeDetRef: ChangeDetectorRef, _elementRef: ElementRef, _itemService: NestedItemService);
    /** Keyboard Event Handler */
    onKeyDown(event: KeyboardEvent): void;
    /** Handler for mouse events */
    onClick(): void;
    /** @hidden */
    ngAfterContentInit(): void;
    /** Method to trigger selected state change */
    changeSelected(selected: boolean): void;
    /** Expanded state change propagation method */
    changeExpandedState(expanded: boolean): void;
    /** Set focus on the element. */
    focus(): void;
    /** Dispatches the click event on the element */
    click(): void;
    /** Add subscription for child focusing */
    private _setFocusSubscription;
    /** Hide link child element from tab key */
    private _makeLinkUnFocusable;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListContentDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<NestedListContentDirective, "[fdNestedListContent], [fd-nested-list-content]", never, { "selected": { "alias": "selected"; "required": false; }; }, { "selectedChange": "selectedChange"; "keyboardTriggered": "keyboardTriggered"; "clicked": "clicked"; }, ["nestedLink", "nestedExpandIcon"], never, true, never>;
}

/**
 * Nested list keyboard service, which uses MenuKeyboardService, to deal with ArrowUp, ArrowDown, Space, Enter.
 * Also has own handling of ArrowLeft and ArrowRight, to open/close the menu if it has any children.
 */
declare class NestedListKeyboardService {
    private keyboardService;
    /**
     * Event, that is thrown always, when the open/close i being called on item components.
     * Also triggers changing of elements, to remove closed/hidden elements
     */
    readonly refresh$: Subject<void>;
    /** @hidden */
    private readonly _destroyRef;
    /** @hidden */
    constructor(keyboardService: MenuKeyboardService);
    /**
     * Function called after refresh$ event is triggered.
     * Refresh the list of NestedItems, that the keyboard support should be provided for
     */
    refreshItems(lists: NestedListInterface[]): void;
    /** Recursive function to get all of the NestedItem elements in correct order. */
    private _getItems;
    /** Method that calls the recursive function, getItems() and gathers all of the items in the NestedList */
    private _getAllListItems;
    /**
     * Keyboard handle function. Uses keyboard support service from MenuComponent, to deal with ArrowUp, ArrowDown, Space, Enter.
     * For ArrowRight, if item is not expanded and has children (list or popup), the open function is triggered.
     * Otherwise it follows ArrowDown functionality.
     * For ArrowLeft, if item is expanded and has children (list or popup), the close function is triggered.
     * Otherwise it follows ArrowUp functionality
     */
    private _handleKeyDown;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListKeyboardService, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<NestedListKeyboardService>;
}

declare class NestedListStateService {
    /**
     * @hidden
     * The condensed state is modified by the parent and read by nested lists.
     */
    condensed: boolean;
    /**
     * @hidden
     */
    selectable: boolean;
    /** @hidden */
    onSelected: Subject<string>;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListStateService, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<NestedListStateService>;
}

declare class NestedItemDirective implements AfterContentInit, NestedItemInterface {
    private _itemService;
    private _keyboardService;
    private _stateService;
    /** Whether item should be expanded */
    set expanded(expanded: boolean);
    /** @hidden */
    get expanded(): boolean;
    /** Event thrown, when expanded state is changed */
    readonly expandedChange: EventEmitter<boolean>;
    /** Event thrown, when any keyboard event is dispatched on this, or link element */
    readonly keyboardTriggered: EventEmitter<KeyboardEvent>;
    /** @hidden */
    fdNestedListItemClass: boolean;
    /**
     * @hidden
     * Reference to the link directive, to allow manipulating the properties of this element.
     */
    linkItem: NestedLinkDirective;
    /**
     * @hidden
     * Mostly used, when this item has list
     * Reference to the content directive, to allow manipulating the properties of this element.
     */
    contentItem: NestedListContentDirective;
    /** @hidden */
    _ariaLevel: Nullable<number>;
    /** @hidden */
    _title: string;
    /** @hidden */
    protected _role: string;
    /** @hidden */
    protected _ariaExpanded: Nullable<boolean>;
    /** @hidden */
    protected _ariaSelected: Nullable<boolean>;
    /** @hidden */
    protected _ariaDisabled: boolean;
    /** @hidden */
    protected _ariaLabel: string;
    /** @hidden */
    protected _ariaHidden: boolean;
    /** @hidden */
    private _expanded;
    /** An RxJS Subject that will kill the data stream upon component’s destruction (for unsubscribing)  */
    private readonly _destroyRef;
    /** Unique element ID */
    private readonly _elementId;
    /** @hidden */
    constructor(_itemService: NestedItemService, _keyboardService: NestedListKeyboardService, _stateService: NestedListStateService);
    /** @hidden */
    ngAfterContentInit(): void;
    /** Check if the item element has any child */
    get hasChildren(): boolean;
    /** Get all of the children item elements */
    get allChildrenItems(): NestedItemInterface[];
    /** Method that expand the item and propagate it to children */
    triggerOpen(): void;
    /** Method that close the item and propagate it to children */
    triggerClose(): void;
    /** Method that toggle the item and propagate it to children */
    toggle(): void;
    /** Method that dispatches `click` event on link item*/
    click(): void;
    /** Method that focuses link item*/
    focus(): void;
    /** Method that provides information if element, or children of this element has passed id */
    containsId(id: string): boolean;
    /**
     * @hidden
     * Propagate open state to all of the children
     */
    private propagateOpenChange;
    /** @hidden */
    private _shouldRefreshKeyboardService;
    /** @hidden */
    private _setUpSubscriptions;
    /** @hidden */
    private _propagateHasChildrenProperty;
    /** Pass this element to popover child item, to allow control `expanded` value */
    private _passItemReferences;
    /** Change of selected state of content or link, if there is any children with I */
    private _selectedChange;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedItemDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<NestedItemDirective, "[fdNestedItem], [fd-nested-list-item]", never, { "expanded": { "alias": "expanded"; "required": false; }; }, { "expandedChange": "expandedChange"; "keyboardTriggered": "keyboardTriggered"; }, ["linkItem", "contentItem"], never, true, never>;
}

interface NestedListItem {
    headerTitle?: string;
    list?: NestedListModel;
    link?: NestedListLink;
    expanded?: boolean;
}
interface NestedListModel {
    textOnly?: boolean;
    items: NestedListItem[];
}
interface NestedListLink {
    icon?: string;
    title: string;
    callback?: () => void;
    href?: string;
    routerLink?: string;
    selected?: boolean;
}

declare class NestedListPopoverComponent implements NestedListPopoverInterface, AfterContentInit {
    /** @hidden
     * For Internal Usage - Gets information about title, which should be displayed inside popover
     */
    title: string;
    /** @hidden */
    popoverComponent: PopoverComponent;
    /** @hidden */
    linkDirective: NestedLinkDirective;
    /** @hidden */
    contentDirective: NestedListContentDirective;
    /**
     * @hidden
     * Reference to parent item, to propagate open and close change from popover.
     */
    parentItemElement: NestedItemInterface;
    /** @hidden */
    open: boolean;
    /** @hidden */
    protected readonly placement: i0.Signal<Placement>;
    /** @hidden */
    private readonly _keyboardNestService;
    /** @hidden */
    private readonly _itemService;
    /** @hidden */
    private readonly _rtlService;
    /** @hidden */
    constructor();
    /** @hidden */
    ngAfterContentInit(): void;
    /**
     * Method called, when open state is changed, from popover component (escape key, outside click).
     */
    handleOpenChange(open: boolean): void;
    /** Returns title of nested link element inside content directive */
    private _getTitle;
    /** @hidden */
    private _listenOnKeyboardRefresh;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListPopoverComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<NestedListPopoverComponent, "fd-nested-list-popover", never, { "title": { "alias": "title"; "required": false; }; }, {}, ["linkDirective", "contentDirective"], ["[fd-nested-list-link]", "[fd-nested-list-content]", "[fd-nested-list]", "fd-prepared-nested-list"], true, never>;
}

/**
 * <div fd-nested-list>
 *  <div fd-nested-list>
 *  </div>
 * </div>
 */
declare class NestedListDirective implements AfterContentInit, NestedListInterface {
    private _nestedItemService;
    private _nestedListKeyboardService;
    private _elementRef;
    private _changeDetectionRef;
    private readonly _nestedListStateService;
    /** In case the user wants to no use icons for items in this list */
    textOnly: boolean;
    /** Aria defines role description for the Nested List Tree. */
    ariaRoledescriptionTree: string;
    /** Aria defines role description for the Nested List MenuBar. */
    ariaRoledescriptionMenuBar: string;
    /** Aria defines aria label for the selected item when the list with disabled selection. */
    ariaLabelSelected: string;
    /** @hidden */
    fdNestedListItemClass: boolean;
    /** @hidden */
    hidden: boolean;
    /**
     * @hidden
     * This variable is mostly to keep track of this list's children. There is not usage of it inside this directive,
     * but it's used by services and NestedItemDirective by itself,
     */
    nestedItems: QueryList<NestedItemDirective>;
    /** @hidden */
    protected _nestedListHeader: NestedListHeaderDirective;
    /** @hidden */
    protected _role: string;
    /** @hidden */
    protected _ariaRoledescription: Nullable<string>;
    /** @hidden */
    protected _ariaHaspopup: Nullable<string>;
    /** @hidden */
    protected _tabindex: string;
    /** @hidden */
    private readonly _translationResolver;
    /** @hidden */
    private readonly _langSignal;
    /** @hidden */
    private readonly _destroyRef;
    /** @hidden */
    private readonly _injector;
    /** @hidden */
    constructor(_nestedItemService: NestedItemService, _nestedListKeyboardService: NestedListKeyboardService, _elementRef: ElementRef, _changeDetectionRef: ChangeDetectorRef, _nestedListStateService: NestedListStateService, _contentDensityObserver: ContentDensityObserver);
    /** @hidden */
    ngAfterContentInit(): void;
    /** @hidden */
    detectChanges(): void;
    /** @hidden */
    private _handleNestedLevel;
    /**
     * @hidden
     * Method, that checks how deep is the list element
     */
    private _getNestedLevel;
    /** @hidden */
    private _setAriaAttributes;
    /** @hidden */
    private _setAccessibilityProperties;
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListDirective, [{ optional: true; }, null, null, null, null, null]>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<NestedListDirective, "[fdNestedList], [fd-nested-list]", never, { "textOnly": { "alias": "textOnly"; "required": false; }; "ariaRoledescriptionTree": { "alias": "ariaRoledescriptionTree"; "required": false; }; "ariaRoledescriptionMenuBar": { "alias": "ariaRoledescriptionMenuBar"; "required": false; }; "ariaLabelSelected": { "alias": "ariaLabelSelected"; "required": false; }; }, {}, ["_nestedListHeader", "nestedItems"], never, true, never>;
}

/**
 * Component for internal usage, allows to generate the nested list from defined object.
 */
declare class PreparedNestedListComponent {
    /**
     * @hidden
     * For internal usage.
     * Defines if the component is first
     */
    first: boolean;
    /** Defines if list should be displayed in condensed mode */
    condensed: boolean;
    /** List configuration*/
    list: Nullable<NestedListModel>;
    /**
     * @hidden
     */
    _nestedListDirective: NestedListDirective;
    /**
     * In prepared nested list, nested items should be taken as reference of View, not Content.
     * There is direct reference to these directives here.
     */
    get nestedListDirective(): NestedListDirective;
    /** @hidden */
    _expandedChange(expanded: boolean, item: NestedListItem): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<PreparedNestedListComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<PreparedNestedListComponent, "fd-prepared-nested-list", never, { "first": { "alias": "first"; "required": false; }; "condensed": { "alias": "condensed"; "required": false; }; "list": { "alias": "list"; "required": false; }; }, {}, never, never, true, never>;
}

/**
 * @deprecated
 * Use direct imports of components and directives.
 */
declare class NestedListModule {
    static ɵfac: i0.ɵɵFactoryDeclaration<NestedListModule, never>;
    static ɵmod: i0.ɵɵNgModuleDeclaration<NestedListModule, never, [typeof NestedListDirective, typeof NestedLinkDirective, typeof NestedItemDirective, typeof NestedListIconComponent, typeof NestedListTitleDirective, typeof NestedListHeaderDirective, typeof NestedListPopoverComponent, typeof PreparedNestedListComponent, typeof NestedListExpandIconComponent, typeof NestedListContentDirective], [typeof NestedListDirective, typeof NestedLinkDirective, typeof NestedItemDirective, typeof NestedListIconComponent, typeof NestedListTitleDirective, typeof NestedListHeaderDirective, typeof NestedListPopoverComponent, typeof PreparedNestedListComponent, typeof NestedListExpandIconComponent, typeof NestedListContentDirective]>;
    static ɵinj: i0.ɵɵInjectorDeclaration<NestedListModule>;
}

export { NestedItemDirective, NestedItemService, NestedLinkDirective, NestedListContentDirective, NestedListDirective, NestedListExpandIconComponent, NestedListHeaderDirective, NestedListIconComponent, NestedListKeyboardService, NestedListModule, NestedListPopoverComponent, NestedListStateService, NestedListTitleDirective, PreparedNestedListComponent };
export type { NestedListItem, NestedListLink, NestedListModel };
