/**
 * @license
 * Copyright Endlessjs. All Rights Reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Directive, ElementRef, HostBinding, Input, } from '@angular/core';
import { filter, takeWhile } from 'rxjs/operators';
import { ElDynamicOverlay } from '../cdk/overlay/dynamic/dynamic-overlay';
import { ElDynamicOverlayHandler } from '../cdk/overlay/dynamic/dynamic-overlay-handler';
import { ElAdjustment, ElPosition } from '../cdk/overlay/overlay-position';
import { ElTrigger } from '../cdk/overlay/overlay-trigger';
import { ElContextMenuComponent } from './context-menu.component';
import { ElMenuService } from '../menu/menu.service';
/**
 * Full featured context menu directive.
 *
 * @stacked-example(Showcase, context-menu/context-menu-showcase.component)
 *
 * Just pass menu items array:
 *
 * ```html
 * <button [elContextMenu]="items"></button>
 * ...
 * items = [{ title: 'Profile' }, { title: 'Log out' }];
 * ```
 * ### Installation
 *
 * Import `ElContextMenuModule` to your feature module.
 * ```ts
 * @NgModule({
 *   imports: [
 *     // ...
 *     ElContextMenuModule,
 *   ],
 * })
 * export class PageModule { }
 * ```
 * Also make sure `ElMenuModule` is imported to your `app.module`.
 * ```ts
 * @NgModule({
 *   imports: [
 *     // ...
 *     ElMenuModule.forRoot(),
 *   ],
 * })
 * export class AppModule { }
 * ```
 *
 * ### Usage
 *
 * If you want to handle context menu clicks you have to pass `elContextMenuTag`
 * param and register to events using ElMenuService.
 * `ElContextMenu` renders plain `ElMenu` inside, so
 * you have to work with it just like with `ElMenu` component:
 *
 * @stacked-example(Menu item click, context-menu/context-menu-click.component)
 *
 * Context menu has different placements, such as: top, bottom, left and right
 * which can be used as following:
 *
 * ```html
 * <button [elContextMenu]="items" elContextMenuPlacement="right"></button>
 * ```
 *
 * ```ts
 * items = [{ title: 'Profile' }, { title: 'Log out' }];
 * ```
 *
 * By default context menu will try to adjust itself to maximally fit viewport
 * and provide the best user experience. It will try to change position of the context menu.
 * If you wanna disable this behaviour just set it falsy value.
 *
 * ```html
 * <button [elContextMenu]="items" elContextMenuAdjustment="counterclockwise"></button>
 * ```
 *
 * ```ts
 * items = [{ title: 'Profile' }, { title: 'Log out' }];
 * ```
 * Context menu has a number of triggers which provides an ability to show and hide the component in different ways:
 *
 * - Click mode shows the component when a user clicks on the host element and hides when the user clicks
 * somewhere on the document outside the component.
 * - Hint provides capability to show the component when the user hovers over the host element
 * and hide when the user hovers out of the host.
 * - Hover works like hint mode with one exception - when the user moves mouse from host element to
 * the container element the component remains open, so that it is possible to interact with it content.
 * - Focus mode is applied when user focuses the element.
 * - Noop mode - the component won't react to the user interaction.
 *
 * @stacked-example(Available Triggers, context-menu/context-menu-modes.component.html)
 *
 * Noop mode is especially useful when you need to control Popover programmatically, for example show/hide
 * as a result of some third-party action, like HTTP request or validation check:
 *
 * @stacked-example(Manual Control, context-menu/context-menu-noop.component)
 *
 * @stacked-example(Manual Control, context-menu/context-menu-right-click.component)
 * */
let ElContextMenuDirective = class ElContextMenuDirective {
    constructor(hostRef, menuService, dynamicOverlayHandler) {
        this.hostRef = hostRef;
        this.menuService = menuService;
        this.dynamicOverlayHandler = dynamicOverlayHandler;
        this.contextMenuHost = true;
        /**
         * Position will be calculated relatively host element based on the position.
         * Can be top, right, bottom and left.
         * */
        this.position = ElPosition.BOTTOM;
        /**
         * Container position will be changes automatically based on this strategy if container can't fit view port.
         * Set this property to any falsy value if you want to disable automatically adjustment.
         * Available values: clockwise, counterclockwise.
         * */
        this.adjustment = ElAdjustment.CLOCKWISE;
        /**
         * Describes when the container will be shown.
         * Available options: `click`, `hover`, `hint`, `focus` and `noop`
         * */
        this.trigger = ElTrigger.CLICK;
        this.alive = true;
        this._items = [];
    }
    /**
     * Basic menu items, will be passed to the internal ElMenuComponent.
     * */
    set items(items) {
        this.validateItems(items);
        this._items = items;
    }
    ;
    ngOnInit() {
        this.dynamicOverlayHandler
            .host(this.hostRef)
            .componentType(ElContextMenuComponent);
    }
    ngOnChanges() {
        this.rebuild();
    }
    ngAfterViewInit() {
        this.dynamicOverlay = this.configureDynamicOverlay()
            .build();
        this.subscribeOnItemClick();
    }
    rebuild() {
        this.dynamicOverlay = this.configureDynamicOverlay()
            .rebuild();
    }
    show() {
        this.dynamicOverlay.show();
    }
    hide() {
        this.dynamicOverlay.hide();
    }
    toggle() {
        this.dynamicOverlay.toggle();
    }
    ngOnDestroy() {
        this.dynamicOverlayHandler.destroy();
    }
    configureDynamicOverlay() {
        return this.dynamicOverlayHandler
            .position(this.position)
            .trigger(this.trigger)
            .adjustment(this.adjustment)
            .context({
            position: this.position,
            items: this._items,
            tag: this.tag,
        });
    }
    /*
     * ElMenuComponent will crash if don't pass menu items to it.
     * So, we just validating them and throw custom obvious error.
     * */
    validateItems(items) {
        if (!items || !items.length) {
            throw Error(`List of menu items expected, but given: ${items}`);
        }
    }
    subscribeOnItemClick() {
        this.menuService.onItemClick()
            .pipe(takeWhile(() => this.alive), filter(({ tag }) => tag === this.tag))
            .subscribe(() => this.hide());
    }
};
__decorate([
    HostBinding('class.context-menu-host'),
    __metadata("design:type", Object)
], ElContextMenuDirective.prototype, "contextMenuHost", void 0);
__decorate([
    Input('elContextMenuPlacement'),
    __metadata("design:type", String)
], ElContextMenuDirective.prototype, "position", void 0);
__decorate([
    Input('elContextMenuAdjustment'),
    __metadata("design:type", String)
], ElContextMenuDirective.prototype, "adjustment", void 0);
__decorate([
    Input('elContextMenuTag'),
    __metadata("design:type", String)
], ElContextMenuDirective.prototype, "tag", void 0);
__decorate([
    Input('elContextMenu'),
    __metadata("design:type", Array),
    __metadata("design:paramtypes", [Array])
], ElContextMenuDirective.prototype, "items", null);
__decorate([
    Input('elContextMenuTrigger'),
    __metadata("design:type", String)
], ElContextMenuDirective.prototype, "trigger", void 0);
ElContextMenuDirective = __decorate([
    Directive({
        selector: '[elContextMenu]',
        providers: [ElDynamicOverlayHandler, ElDynamicOverlay],
    }),
    __metadata("design:paramtypes", [ElementRef,
        ElMenuService,
        ElDynamicOverlayHandler])
], ElContextMenuDirective);
export { ElContextMenuDirective };
//# sourceMappingURL=context-menu.directive.js.map