import * as i0 from '@angular/core';
import { ElementRef, EventEmitter, TemplateRef, Injector, OnDestroy, ViewContainerRef, OnInit, AfterViewInit, ChangeDetectorRef, QueryList, NgZone, InjectionToken } from '@angular/core';
import { FocusableOption } from '@angular/cdk/a11y';
import { HasElementRef, Nullable } from '@fundamental-ngx/cdk/utils';
import { Observable } from 'rxjs';

interface OverflowLayoutFocusableItem extends FocusableOption {
    focusable: boolean;
    navigable: boolean;
    hidden: boolean;
    elementRef: ElementRef<HTMLElement>;
    focus(): void;
}

interface OverflowItem {
    /**
     * Whether to enforce the visibility of the item.
     */
    forceVisibility: boolean;
    /**
     * Element reference.
     */
    elmRef: ElementRef;
    /**
     * Whether the item is hidden.
     */
    hidden: boolean;
    /**
     * Event emitted when `hidden` property has been changed.
     */
    hiddenChange: EventEmitter<boolean>;
    /**
     * Focusable item for keyboard navigation.
     */
    focusableItem: OverflowLayoutFocusableItem;
}

type OverflowItemDirectiveContext<T = any> = {
    $implicit: boolean;
    index: number;
    globalIndex: number;
    first: boolean;
    last: boolean;
    item?: T;
    injector: Injector;
};
interface OverflowItemRef<T = any> {
    /**
     * Element reference.
     */
    elementRef: ElementRef<HTMLElement>;
    /**
     * Overflow item directive instance.
     */
    overflowItem: OverflowItem;
    /**
     * Whether the item is hidden.
     */
    hidden: boolean;
    /** Index of the item in the visible or hidden array of Overflow Layout Component's items. */
    index: number;
    /**
     * The index of the item in the array of items.
     */
    globalIndex: number;
    /** Whether this item is last in the array. */
    first: boolean;
    /** Whether this item is first in the array. */
    last: boolean;
    /** Whether the item is softly hidden. */
    softHidden: boolean;
    /**
     * Template reference of the directive.
     */
    templateRef: TemplateRef<OverflowItemDirectiveContext<T>>;
    /** Item instance. Used for correct autocomplete. */
    item: T;
    /** Injector of the directive. */
    readonly injector: Injector;
    /**
     * Sets the element reference of the directive.
     * @param elmRef Element reference.
     */
    setElementRef(elmRef: ElementRef): void;
    /**
     * Sets the overflow item directive.
     * @param item Overflow item directive.
     */
    setOverflowItem(item: OverflowItem): void;
}

type OverflowExpandDirectiveContext<T extends any[] = any[]> = {
    $implicit: OverflowItemRef<T[number]>[];
};
interface OverflowExpand<T extends any[] = any[]> {
    /**
     * Template reference of the directive.
     */
    templateRef: TemplateRef<OverflowExpandDirectiveContext<T>>;
}

/**
 * Structural directive which is responsible for rendering the "More" button and handling further logic.
 */
declare class OverflowExpandDirective<T extends any[] = any[]> implements OverflowExpand<T> {
    templateRef: TemplateRef<OverflowExpandDirectiveContext<T>>;
    /** Items to expand */
    fdOverflowExpandItems: T;
    /** @hidden */
    constructor(templateRef: TemplateRef<OverflowExpandDirectiveContext<T>>);
    /** @hidden */
    static ngTemplateContextGuard(dir: OverflowExpandDirective, ctx: OverflowExpandDirectiveContext): ctx is OverflowExpandDirectiveContext;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowExpandDirective<any>, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowExpandDirective<any>, "[fdOverflowExpand]", never, { "fdOverflowExpandItems": { "alias": "fdOverflowExpandItems"; "required": false; }; }, {}, never, never, true, never>;
}

/**
 * Directive to hide component without actual destroying of the component instance.
 */
declare class OverflowItemContainerRefDirective implements OnDestroy {
    private _templateRef;
    private _viewContainerRef;
    /** @hidden */
    private _viewRef;
    /** @hidden */
    private _detached;
    /** @hidden */
    private _hidden;
    /**
     * Shows or hides element without destroying the view itself.
     * @param value
     */
    set hidden(value: boolean);
    /** @hidden */
    constructor(_templateRef: TemplateRef<any>, _viewContainerRef: ViewContainerRef);
    /** @hidden */
    ngOnDestroy(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowItemContainerRefDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowItemContainerRefDirective, "[fdOverflowItemContainerRef]", never, {}, {}, never, never, true, never>;
}

/**
 * Structural directive which is used to pass the context of the item to the template engine.
 */
declare class OverflowItemRefDirective<T = any> implements OverflowItemRef<T>, HasElementRef {
    templateRef: TemplateRef<OverflowItemDirectiveContext<T>>;
    /** Item instance. Used for correct autocomplete. */
    item: T;
    /**
     * Element ref of the `fdOverflowLayoutItem` directive.
     */
    elementRef: ElementRef<HTMLElement>;
    /**
     * `fdOverflowLayoutItem` directive.
     */
    overflowItem: OverflowItem;
    /**
     * Whether the item is hidden.
     */
    set hidden(value: boolean);
    get hidden(): boolean;
    /** @hidden */
    _hidden: boolean;
    /** Index of the item in the visible or hidden array of Overflow Layout Component's items. */
    index: number;
    /**
     * The index of the item in the array of items.
     */
    globalIndex: number;
    /** Whether this item is last in the array. */
    first: boolean;
    /** Whether this item is first in the array. */
    last: boolean;
    /** Whether the item is softly hidden. */
    softHidden: boolean;
    /** @hidden */
    readonly injector: i0.Injector;
    /** @hidden */
    constructor(templateRef: TemplateRef<OverflowItemDirectiveContext<T>>);
    /** @hidden */
    static ngTemplateContextGuard(dir: OverflowItemRefDirective, ctx: OverflowItemDirectiveContext): ctx is OverflowItemDirectiveContext;
    /**
     * Sets the element reference of the `fdOverflowLayoutItem` directive.`
     * @param elmRef
     */
    setElementRef(elmRef: ElementRef): void;
    /**
     * Sets the `fdOverflowLayoutItem` directive.
     * @param item
     */
    setOverflowItem(item: OverflowItem): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowItemRefDirective<any>, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowItemRefDirective<any>, "[fdOverflowItemRef]", never, { "item": { "alias": "fdOverflowItemRef"; "required": false; }; }, {}, never, never, true, never>;
}

declare class OverflowLayoutItemContainerDirective {
    elementRef: ElementRef;
    /**
     * Whether this item is the first one in the array.
     */
    last: boolean;
    /**
     * Whether this item is the last one in the array.
     */
    first: boolean;
    /**
     * Whether this item is softly hidden. Used during free space calculation without flickering of the items.
     */
    softHidden: boolean;
    /**
     * Container reference.
     */
    containerRef: OverflowItemContainerRefDirective;
    /** @hidden */
    protected readonly _initialClass = "fd-overflow-layout__item";
    /** @hidden */
    constructor(elementRef: ElementRef);
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutItemContainerDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowLayoutItemContainerDirective, "[fdOverflowLayoutItemContainer]", never, { "last": { "alias": "last"; "required": false; }; "first": { "alias": "first"; "required": false; }; "softHidden": { "alias": "softHidden"; "required": false; }; }, {}, ["containerRef"], never, true, never>;
}

interface OverflowPopoverContent {
    /**
     * Array of hidden items.
     */
    items: OverflowItemRef[];
    /**
     * Focuses the first focusable item in the container.
     */
    focusFirstTabbableElement(): void;
}

interface OverflowContainer {
    registerPopoverContent(content: OverflowPopoverContent): void;
}

interface OverflowLayoutConfig {
    items: OverflowItemRef[];
    focusableItems: OverflowLayoutFocusableItem[];
    visibleItems: OverflowLayoutItemContainerDirective[];
    itemsWrapper: HTMLElement;
    showMoreContainer?: HTMLElement;
    layoutContainerElement: HTMLElement;
    maxVisibleItems: number;
    direction: 'left' | 'right';
    enableKeyboardNavigation: boolean;
    reverseHiddenItems: boolean;
}
declare class OverflowLayoutListeningResult {
    /** Whether to show more button */
    showMore: boolean;
    /** Overflow item s */
    items: OverflowItemRef[];
    /** Hidden overflow items */
    hiddenItems: OverflowItemRef[];
    /** Visible overflow items */
    visibleItems: OverflowItemRef[];
}
declare class OverflowLayoutService implements OnDestroy {
    private _elRef;
    /**
     * Overflow Layout config.
     */
    config: OverflowLayoutConfig;
    /**
     * Overflow Layout calculation result.
     */
    result: OverflowLayoutListeningResult;
    /** @hidden */
    private _listenToItemResize;
    /** @hidden */
    private readonly _subscription;
    /** @hidden */
    private _allItems;
    /** @hidden */
    private _hiddenItems;
    /** @hidden */
    private _detectChanges$;
    /** @hidden */
    private _result$;
    /**
     * Observable which emits when changes detection is required.
     */
    get detectChanges(): Observable<void>;
    /**
     * Observable which emits when new calculation result is available.
     */
    get onResult(): Observable<OverflowLayoutListeningResult>;
    /** @hidden */
    constructor(_elRef: ElementRef<HTMLElement>);
    /** @hidden */
    ngOnDestroy(): void;
    /** @hidden */
    startListening(config: OverflowLayoutConfig): void;
    /** @hidden */
    setConfig(config: OverflowLayoutConfig): void;
    /**
     * Calculates available space for items and hides items that are not fitting into the container.
     */
    fitVisibleItems(): void;
    /** @hidden */
    private _getForcedItemsIndexes;
    /**
     * @hidden
     * Returns combined width of the element including margins.
     * @param element Element to calculate width of.
     */
    private _getElementWidth;
    /** @hidden */
    private _emitResult;
    /** @hidden */
    private _listenToSizeChanges;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutService, never>;
    static ɵprov: i0.ɵɵInjectableDeclaration<OverflowLayoutService>;
}

declare class OverflowLayoutComponent implements OnInit, AfterViewInit, OnDestroy, OverflowContainer {
    private readonly _elementRef;
    private readonly _ngZone;
    protected _cdr: ChangeDetectorRef;
    protected _overflowLayoutService: OverflowLayoutService;
    /**
     * Maximum amount of visible items.
     */
    set maxVisibleItems(value: number);
    get maxVisibleItems(): number;
    /**
     * Keyboard event to listen for keyboard navigation through items.
     */
    navigationTrigger: 'keyup' | 'keydown';
    /** Direction of the fitting items calculation. */
    showMorePosition: 'left' | 'right';
    /** Whether the show more button should be rendered */
    renderShowMoreButton: boolean;
    /** Whether to render hidden items in reverse order. */
    reverseHiddenItems: boolean;
    /** Whether to enable keyboard navigation. */
    enableKeyboardNavigation: boolean;
    /** Aria role of the overflow layout. */
    ariaRole: string;
    /**
     * Event, triggered when amount of visible items has been changed.
     */
    visibleItemsCount: EventEmitter<number>;
    /**
     * Event, triggered when amount of hidden items has been changed.
     */
    hiddenItemsCount: EventEmitter<number>;
    /**
     * Event, triggered when hidden items have been changed.
     */
    hiddenItemsChange: EventEmitter<OverflowItemRef<any>[]>;
    /**
     * @hidden
     * List of items to display.
     */
    _items: QueryList<OverflowItemRef>;
    /**
     * @hidden
     * Template for the custom "More" button.
     */
    _moreButton: Nullable<OverflowExpand>;
    /**
     * @hidden
     * List of items that can be focused
     */
    _focusableOverflowItems: QueryList<OverflowLayoutFocusableItem>;
    /**
     * @hidden
     * List of rendered items.
     */
    _visibleItems: QueryList<OverflowLayoutItemContainerDirective>;
    /**
     * @hidden
     * Items wrapper directive.
     */
    _itemsWrapper: ElementRef<HTMLElement>;
    /**
     * @hidden
     * Layout container element.
     */
    _layoutContainer: ElementRef<HTMLDivElement>;
    /**
     * @hidden
     * "More" button container element.
     */
    _showMoreContainer: ElementRef<HTMLDivElement>;
    /** @hidden */
    readonly _initialClass = "fd-overflow-layout";
    /** @hidden */
    _allItems: OverflowItemRef[];
    /** @hidden */
    _hiddenItems: OverflowItemRef[];
    /** @hidden */
    _showMore: boolean;
    /** @hidden */
    private readonly _subscription;
    /** @hidden */
    private _overflowPopoverContent;
    /** @hidden */
    private _fillTrigger$;
    /** @hidden */
    private _maxVisibleItems;
    /** @hidden */
    private _canListenToResize;
    /** @hidden */
    private _dir;
    /** @hidden */
    private _keyboardEventsManager;
    /** @hidden */
    private readonly _rtl;
    /** @hidden */
    constructor(_elementRef: ElementRef<HTMLElement>, _ngZone: NgZone, _cdr: ChangeDetectorRef, _overflowLayoutService: OverflowLayoutService);
    /** Overflow Layout more button text */
    moreItemsButtonText: (hiddenItemsCount: number) => string;
    /** @hidden */
    private get _config();
    /** @hidden */
    ngOnInit(): void;
    /** @hidden */
    ngAfterViewInit(): void;
    /** @hidden */
    ngOnDestroy(): void;
    /**
     * Triggers layout recalculation of the items.
     */
    triggerRecalculation(): void;
    /**
     * Sets current focused element.
     * @param element Element that needs to be focused.
     */
    setFocusedElement(element: OverflowLayoutFocusableItem): void;
    /**
     * Registers popover content directive for main component.
     * @param content {OverflowPopoverContent} directive
     */
    registerPopoverContent(content: OverflowPopoverContent): void;
    /** @hidden */
    _onPopoverStateChange(opened: boolean): void;
    /** @hidden */
    private _setupKeyboardListener;
    /** @hidden */
    private _setFocusKeyManager;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<OverflowLayoutComponent, "fd-overflow-layout", never, { "maxVisibleItems": { "alias": "maxVisibleItems"; "required": false; }; "navigationTrigger": { "alias": "navigationTrigger"; "required": false; }; "showMorePosition": { "alias": "showMorePosition"; "required": false; }; "renderShowMoreButton": { "alias": "renderShowMoreButton"; "required": false; }; "reverseHiddenItems": { "alias": "reverseHiddenItems"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "ariaRole": { "alias": "ariaRole"; "required": false; }; "moreItemsButtonText": { "alias": "moreItemsButtonText"; "required": false; }; }, { "visibleItemsCount": "visibleItemsCount"; "hiddenItemsCount": "hiddenItemsCount"; "hiddenItemsChange": "hiddenItemsChange"; }, ["_moreButton", "_items", "_focusableOverflowItems"], never, true, never>;
    static ngAcceptInputType_renderShowMoreButton: unknown;
}

declare class OverflowLayoutFocusableItemDirective implements OverflowLayoutFocusableItem, OnInit {
    private readonly _overflowContainer;
    private readonly _overflowItem;
    readonly elementRef: ElementRef<HTMLElement>;
    /** Whether the item should be focusable. */
    focusable: boolean;
    /** Whether the item should be navigable via keyboard. */
    navigable: boolean;
    /** @hidden */
    protected get _tabindex(): number;
    /** Whether the item is hidden. */
    get hidden(): boolean;
    /** @hidden */
    constructor(_overflowContainer: OverflowLayoutComponent, _overflowItem: OverflowItem, elementRef: ElementRef<HTMLElement>);
    /** @hidden */
    protected _onFocus(): void;
    /** @hidden */
    ngOnInit(): void;
    /** @hidden */
    focus(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutFocusableItemDirective, [null, { optional: true; }, null]>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowLayoutFocusableItemDirective, "[fdOverflowLayoutFocusableItem], [fdOverflowLayoutItem][focusable]", never, { "focusable": { "alias": "focusable"; "required": false; }; "navigable": { "alias": "navigable"; "required": false; }; }, {}, never, never, true, never>;
}

/**
 * Directive to mark element as part of for Overflow Layout Component items.
 */
declare class OverflowLayoutItemDirective implements OverflowItem, OnInit {
    /** Whether to force the visibility of the item. */
    set forceVisibility(value: boolean);
    get forceVisibility(): boolean;
    /**
     * Event emitted when `hidden` property has been changed.
     */
    hiddenChange: EventEmitter<boolean>;
    /**
     * Whether the item is hidden.
     */
    set hidden(value: boolean);
    get hidden(): boolean;
    /**
     * Focusable item for keyboard navigation.
     */
    focusableItem: OverflowLayoutFocusableItem;
    /** Reference to the element */
    elmRef: ElementRef<any>;
    /** @hidden */
    protected _overflowItemRef: OverflowItemRef | null;
    /** @hidden */
    private _forceVisibility;
    /** @hidden */
    private _overflowContainer;
    /** @hidden */
    ngOnInit(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutItemDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowLayoutItemDirective, "[fdOverflowLayoutItem]", never, { "forceVisibility": { "alias": "forceVisibility"; "required": false; }; }, { "hiddenChange": "hiddenChange"; }, never, never, true, never>;
}

/**
 * Directive to wrap Overlay Layout "More" popover content.
 * Used to apply keyboard navigation through the items.
 */
declare class OverflowLayoutPopoverContentDirective implements OverflowPopoverContent, OnDestroy {
    private _overflowContainer;
    /**
     * Array of hidden items.
     */
    set items(value: OverflowItemRef[]);
    /** @hidden */
    protected readonly _initialClass = "fd-overflow-layout__popover-container";
    /** @hidden */
    private _keyboardEventsManager;
    /** @hidden */
    private _items;
    /** @hidden */
    private readonly _dir;
    /** @hidden */
    private readonly _rtlService;
    /** @hidden */
    constructor(_overflowContainer: OverflowContainer);
    /** @hidden */
    keyUpHandler(event: KeyboardEvent): void;
    /**
     * Focuses on the first tabbable element inside directive's element.
     */
    focusFirstTabbableElement(): void;
    /** @hidden */
    ngOnDestroy(): void;
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutPopoverContentDirective, never>;
    static ɵdir: i0.ɵɵDirectiveDeclaration<OverflowLayoutPopoverContentDirective, "[fdOverflowLayoutPopoverContent]", never, { "items": { "alias": "items"; "required": false; }; }, {}, never, never, true, never>;
}

/**
 * @deprecated
 * Use direct imports of OverflowLayoutComponent,
        OverflowItemRefDirective,
        OverflowExpandDirective,
        OverflowLayoutItemDirective,
        OverflowItemContainerRefDirective,
        OverflowLayoutPopoverContentDirective,
        OverflowLayoutItemContainerDirective,
        OverflowLayoutFocusableItemDirective
 */
declare class OverflowLayoutModule {
    static ɵfac: i0.ɵɵFactoryDeclaration<OverflowLayoutModule, never>;
    static ɵmod: i0.ɵɵNgModuleDeclaration<OverflowLayoutModule, never, [typeof OverflowLayoutComponent, typeof OverflowItemRefDirective, typeof OverflowExpandDirective, typeof OverflowLayoutItemDirective, typeof OverflowItemContainerRefDirective, typeof OverflowLayoutPopoverContentDirective, typeof OverflowLayoutItemContainerDirective, typeof OverflowLayoutFocusableItemDirective], [typeof OverflowLayoutComponent, typeof OverflowItemRefDirective, typeof OverflowExpandDirective, typeof OverflowLayoutItemDirective, typeof OverflowItemContainerRefDirective, typeof OverflowLayoutPopoverContentDirective, typeof OverflowLayoutItemContainerDirective, typeof OverflowLayoutFocusableItemDirective]>;
    static ɵinj: i0.ɵɵInjectorDeclaration<OverflowLayoutModule>;
}

declare const FD_OVERFLOW_CONTAINER: InjectionToken<OverflowContainer>;

declare const FD_OVERFLOW_EXPAND: InjectionToken<OverflowExpand<any[]>>;

declare const FD_OVERFLOW_ITEM_REF: InjectionToken<OverflowItemRef<any>>;

declare const FD_OVERFLOW_ITEM: InjectionToken<OverflowItem>;

export { FD_OVERFLOW_CONTAINER, FD_OVERFLOW_EXPAND, FD_OVERFLOW_ITEM, FD_OVERFLOW_ITEM_REF, OverflowExpandDirective, OverflowItemContainerRefDirective, OverflowItemRefDirective, OverflowLayoutComponent, OverflowLayoutFocusableItemDirective, OverflowLayoutItemContainerDirective, OverflowLayoutItemDirective, OverflowLayoutListeningResult, OverflowLayoutModule, OverflowLayoutPopoverContentDirective, OverflowLayoutService };
export type { OverflowExpand, OverflowExpandDirectiveContext, OverflowItem, OverflowItemDirectiveContext, OverflowItemRef, OverflowLayoutConfig, OverflowPopoverContent };
