angular-confirmation-popover
Version: 
An angular 15.0+ bootstrap confirmation popover
370 lines (360 loc) • 20.6 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Directive, Input, Component, EventEmitter, Injector, Output, HostListener, InjectionToken, NgModule } from '@angular/core';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import { positionElements } from 'positioning';
class ConfirmationPopoverOptions {
    constructor() {
        this.confirmText = 'Confirm';
        this.cancelText = 'Cancel';
        this.confirmButtonType = 'success';
        this.cancelButtonType = 'outline-secondary';
        this.placement = 'top';
        this.hideConfirmButton = false;
        this.hideCancelButton = false;
        this.popoverClass = '';
        this.appendToBody = false;
        this.reverseButtonOrder = false;
        this.closeOnOutsideClick = true;
    }
}
ConfirmationPopoverOptions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
ConfirmationPopoverOptions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverOptions });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverOptions, decorators: [{
            type: Injectable
        }] });
/**
 * @internal
 */
class ConfirmationPopoverWindowOptions extends ConfirmationPopoverOptions {
}
ConfirmationPopoverWindowOptions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverWindowOptions, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
ConfirmationPopoverWindowOptions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverWindowOptions });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverWindowOptions, decorators: [{
            type: Injectable
        }] });
/**
 * A helper directive to focus buttons. You will only need this if using a custom template
 */
class FocusDirective {
    constructor(elm) {
        this.elm = elm;
    }
    ngOnChanges(changes) {
        if (changes.mwlFocus && this.mwlFocus === true) {
            this.elm.nativeElement.focus();
        }
    }
}
FocusDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: FocusDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
FocusDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.8", type: FocusDirective, selector: "[mwlFocus]", inputs: { mwlFocus: "mwlFocus" }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: FocusDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mwlFocus]',
                }]
        }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { mwlFocus: [{
                type: Input
            }] } });
/**
 * @internal
 */
class ConfirmationPopoverWindowComponent {
    constructor(options) {
        this.options = options;
    }
    ngAfterViewInit() {
        this.options.onAfterViewInit();
    }
}
ConfirmationPopoverWindowComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverWindowComponent, deps: [{ token: ConfirmationPopoverWindowOptions }], target: i0.ɵɵFactoryTarget.Component });
ConfirmationPopoverWindowComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.8", type: ConfirmationPopoverWindowComponent, selector: "mwl-confirmation-popover-window", ngImport: i0, template: "<ng-template #defaultTemplate let-options=\"options\">\n  <div\n    [ngClass]=\"[\n      'popover',\n      options.placement,\n      'popover-' + options.placement,\n      'bs-popover-' + options.placement,\n      options.popoverClass\n    ]\"\n  >\n    <div class=\"popover-arrow arrow\"></div>\n    <h3\n      class=\"popover-title popover-header\"\n      [innerHTML]=\"options.popoverTitle\"\n    ></h3>\n    <div class=\"popover-content popover-body\">\n      <p [innerHTML]=\"options.popoverMessage\"></p>\n      <div\n        class=\"confirm-btns\"\n        [class.confirm-btns-reversed]=\"options.reverseButtonOrder\"\n      >\n        <div class=\"confirm-btn-container\" *ngIf=\"!options.hideCancelButton\">\n          <button\n            type=\"button\"\n            [mwlFocus]=\"options.focusButton === 'cancel'\"\n            [class]=\"'btn btn-block btn-' + options.cancelButtonType\"\n            (click)=\"options.onCancel({ clickEvent: $event })\"\n            [innerHtml]=\"options.cancelText\"\n          ></button>\n        </div>\n        <div class=\"confirm-btn-container\" *ngIf=\"!options.hideConfirmButton\">\n          <button\n            type=\"button\"\n            [mwlFocus]=\"options.focusButton === 'confirm'\"\n            [class]=\"'btn btn-block btn-' + options.confirmButtonType\"\n            (click)=\"options.onConfirm({ clickEvent: $event })\"\n            [innerHtml]=\"options.confirmText\"\n          ></button>\n        </div>\n      </div>\n    </div>\n  </div>\n</ng-template>\n<ng-template\n  [ngTemplateOutlet]=\"options.customTemplate || defaultTemplate\"\n  [ngTemplateOutletContext]=\"{ options: options }\"\n>\n</ng-template>\n", styles: [".popover{display:block}.bs-popover-top .arrow,.bs-popover-bottom .arrow{left:50%}.bs-popover-left .arrow,.bs-popover-right .arrow{top:calc(50% - 8px)}.btn{transition:none}.confirm-btns{display:flex;justify-content:space-around}.confirm-btn-container{flex-basis:50%}.confirm-btn-container:not(:first-child){margin-left:4px}.confirm-btn-container:not(:last-child){margin-right:4px}.confirm-btns-reversed{flex-direction:row-reverse}.confirm-btns-reversed .confirm-btn-container:not(:first-child){margin-right:4px;margin-left:0}.confirm-btns-reversed .confirm-btn-container:not(:last-child){margin-right:0;margin-left:4px}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: FocusDirective, selector: "[mwlFocus]", inputs: ["mwlFocus"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverWindowComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mwl-confirmation-popover-window', template: "<ng-template #defaultTemplate let-options=\"options\">\n  <div\n    [ngClass]=\"[\n      'popover',\n      options.placement,\n      'popover-' + options.placement,\n      'bs-popover-' + options.placement,\n      options.popoverClass\n    ]\"\n  >\n    <div class=\"popover-arrow arrow\"></div>\n    <h3\n      class=\"popover-title popover-header\"\n      [innerHTML]=\"options.popoverTitle\"\n    ></h3>\n    <div class=\"popover-content popover-body\">\n      <p [innerHTML]=\"options.popoverMessage\"></p>\n      <div\n        class=\"confirm-btns\"\n        [class.confirm-btns-reversed]=\"options.reverseButtonOrder\"\n      >\n        <div class=\"confirm-btn-container\" *ngIf=\"!options.hideCancelButton\">\n          <button\n            type=\"button\"\n            [mwlFocus]=\"options.focusButton === 'cancel'\"\n            [class]=\"'btn btn-block btn-' + options.cancelButtonType\"\n            (click)=\"options.onCancel({ clickEvent: $event })\"\n            [innerHtml]=\"options.cancelText\"\n          ></button>\n        </div>\n        <div class=\"confirm-btn-container\" *ngIf=\"!options.hideConfirmButton\">\n          <button\n            type=\"button\"\n            [mwlFocus]=\"options.focusButton === 'confirm'\"\n            [class]=\"'btn btn-block btn-' + options.confirmButtonType\"\n            (click)=\"options.onConfirm({ clickEvent: $event })\"\n            [innerHtml]=\"options.confirmText\"\n          ></button>\n        </div>\n      </div>\n    </div>\n  </div>\n</ng-template>\n<ng-template\n  [ngTemplateOutlet]=\"options.customTemplate || defaultTemplate\"\n  [ngTemplateOutletContext]=\"{ options: options }\"\n>\n</ng-template>\n", styles: [".popover{display:block}.bs-popover-top .arrow,.bs-popover-bottom .arrow{left:50%}.bs-popover-left .arrow,.bs-popover-right .arrow{top:calc(50% - 8px)}.btn{transition:none}.confirm-btns{display:flex;justify-content:space-around}.confirm-btn-container{flex-basis:50%}.confirm-btn-container:not(:first-child){margin-left:4px}.confirm-btn-container:not(:last-child){margin-right:4px}.confirm-btns-reversed{flex-direction:row-reverse}.confirm-btns-reversed .confirm-btn-container:not(:first-child){margin-right:4px;margin-left:0}.confirm-btns-reversed .confirm-btn-container:not(:last-child){margin-right:0;margin-left:4px}\n"] }]
        }], ctorParameters: function () { return [{ type: ConfirmationPopoverWindowOptions }]; } });
/**
 All properties can be set on the directive as attributes like so (use `ConfirmationPopoverModule.forRoot()` to configure them globally):
 ```html
 <button
   class="btn btn-outline-secondary"
   mwlConfirmationPopover
   [popoverTitle]="popoverTitle"
   [popoverMessage]="popoverMessage"
   placement="left"
   (confirm)="confirmClicked = true"
   (cancel)="cancelClicked = true"
   [(isOpen)]="isOpen">
    Show confirm popover!
  </button>
  ```
 */
class ConfirmationPopoverDirective {
    /**
     * @internal
     */
    constructor(viewContainerRef, elm, defaultOptions, renderer) {
        this.viewContainerRef = viewContainerRef;
        this.elm = elm;
        this.defaultOptions = defaultOptions;
        this.renderer = renderer;
        /**
         * Whether to disable showing the popover. Default `false`.
         */
        this.isDisabled = false;
        /**
         * Will open or show the popover when changed.
         * Can be sugared with `isOpenChange` to emulate 2-way binding like so `[(isOpen)]="isOpen"`
         */
        this.isOpen = false;
        /**
         * Will emit when the popover is opened or closed
         */
        this.isOpenChange = new EventEmitter(true);
        /**
         * An expression that is called when the confirm button is clicked.
         */
        this.confirm = new EventEmitter();
        /**
         * An expression that is called when the cancel button is clicked.
         */
        this.cancel = new EventEmitter();
        this.eventListeners = [];
    }
    /**
     * @internal
     */
    ngOnInit() {
        this.isOpenChange.emit(false);
    }
    /**
     * @internal
     */
    ngOnChanges(changes) {
        if (changes.isOpen) {
            if (changes.isOpen.currentValue === true) {
                this.showPopover();
            }
            else {
                this.hidePopover();
            }
        }
    }
    /**
     * @internal
     */
    ngOnDestroy() {
        this.hidePopover();
    }
    /**
     * @internal
     */
    onConfirm(event) {
        this.confirm.emit(event);
        this.hidePopover();
    }
    /**
     * @internal
     */
    onCancel(event) {
        this.cancel.emit(event);
        this.hidePopover();
    }
    /**
     * @internal
     */
    togglePopover() {
        if (!this.popover) {
            this.showPopover();
        }
        else {
            this.hidePopover();
        }
    }
    onDocumentClick(event) {
        const closeOnOutsideClick = typeof this.closeOnOutsideClick !== 'undefined'
            ? this.closeOnOutsideClick
            : this.defaultOptions.closeOnOutsideClick;
        if (this.popover &&
            !this.elm.nativeElement.contains(event.target) &&
            !this.popover.location.nativeElement.contains(event.target) &&
            closeOnOutsideClick) {
            this.hidePopover();
        }
    }
    showPopover() {
        if (!this.popover && !this.isDisabled) {
            // work around for https://github.com/mattlewis92/angular-confirmation-popover/issues/65
            // otherwise the document click event gets fired after the click event
            // that triggered the popover to open (no idea why this is so)
            setTimeout(() => {
                this.eventListeners = [
                    this.renderer.listen('document', 'click', (event) => this.onDocumentClick(event)),
                    this.renderer.listen('document', 'touchend', (event) => this.onDocumentClick(event)),
                    this.renderer.listen('window', 'resize', () => this.positionPopover()),
                ];
            });
            const options = new ConfirmationPopoverWindowOptions();
            Object.assign(options, this.defaultOptions, {
                onConfirm: (event) => {
                    this.onConfirm(event);
                },
                onCancel: (event) => {
                    this.onCancel(event);
                },
                onAfterViewInit: () => {
                    this.positionPopover();
                },
            });
            const optionalParams = [
                'confirmText',
                'cancelText',
                'placement',
                'confirmButtonType',
                'cancelButtonType',
                'focusButton',
                'hideConfirmButton',
                'hideCancelButton',
                'popoverClass',
                'appendToBody',
                'customTemplate',
                'reverseButtonOrder',
                'popoverTitle',
                'popoverMessage',
            ];
            optionalParams.forEach((param) => {
                if (typeof this[param] !== 'undefined') {
                    options[param] = this[param];
                }
            });
            const childInjector = Injector.create({
                providers: [
                    {
                        provide: ConfirmationPopoverWindowOptions,
                        useValue: options,
                    },
                ],
            });
            this.popover = this.viewContainerRef.createComponent(ConfirmationPopoverWindowComponent, { injector: childInjector });
            if (options.appendToBody) {
                document.body.appendChild(this.popover.location.nativeElement);
            }
            this.isOpenChange.emit(true);
        }
    }
    positionPopover() {
        if (this.popover) {
            const popoverElement = this.popover.location.nativeElement.children[0];
            positionElements(this.elm.nativeElement, popoverElement, this.placement || this.defaultOptions.placement, this.appendToBody || this.defaultOptions.appendToBody);
        }
    }
    hidePopover() {
        if (this.popover) {
            this.popover.destroy();
            delete this.popover;
            this.isOpenChange.emit(false);
            this.eventListeners.forEach((fn) => fn());
            this.eventListeners = [];
        }
    }
}
ConfirmationPopoverDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.ElementRef }, { token: ConfirmationPopoverOptions }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
ConfirmationPopoverDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.8", type: ConfirmationPopoverDirective, selector: "[mwlConfirmationPopover]", inputs: { popoverTitle: "popoverTitle", popoverMessage: "popoverMessage", confirmText: "confirmText", cancelText: "cancelText", placement: "placement", confirmButtonType: "confirmButtonType", cancelButtonType: "cancelButtonType", focusButton: "focusButton", hideConfirmButton: "hideConfirmButton", hideCancelButton: "hideCancelButton", isDisabled: "isDisabled", isOpen: "isOpen", customTemplate: "customTemplate", popoverClass: "popoverClass", appendToBody: "appendToBody", reverseButtonOrder: "reverseButtonOrder", closeOnOutsideClick: "closeOnOutsideClick" }, outputs: { isOpenChange: "isOpenChange", confirm: "confirm", cancel: "cancel" }, host: { listeners: { "click": "togglePopover()" } }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mwlConfirmationPopover]',
                }]
        }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ElementRef }, { type: ConfirmationPopoverOptions }, { type: i0.Renderer2 }]; }, propDecorators: { popoverTitle: [{
                type: Input
            }], popoverMessage: [{
                type: Input
            }], confirmText: [{
                type: Input
            }], cancelText: [{
                type: Input
            }], placement: [{
                type: Input
            }], confirmButtonType: [{
                type: Input
            }], cancelButtonType: [{
                type: Input
            }], focusButton: [{
                type: Input
            }], hideConfirmButton: [{
                type: Input
            }], hideCancelButton: [{
                type: Input
            }], isDisabled: [{
                type: Input
            }], isOpen: [{
                type: Input
            }], customTemplate: [{
                type: Input
            }], isOpenChange: [{
                type: Output
            }], confirm: [{
                type: Output
            }], cancel: [{
                type: Output
            }], popoverClass: [{
                type: Input
            }], appendToBody: [{
                type: Input
            }], reverseButtonOrder: [{
                type: Input
            }], closeOnOutsideClick: [{
                type: Input
            }], togglePopover: [{
                type: HostListener,
                args: ['click']
            }] } });
const USER_OPTIONS = new InjectionToken('confirmation popover user options');
function optionsFactory(userOptions) {
    const options = new ConfirmationPopoverOptions();
    Object.assign(options, userOptions);
    return options;
}
class ConfirmationPopoverModule {
    static forRoot(options = {}) {
        return {
            ngModule: ConfirmationPopoverModule,
            providers: [
                {
                    provide: USER_OPTIONS,
                    useValue: options,
                },
                {
                    provide: ConfirmationPopoverOptions,
                    useFactory: optionsFactory,
                    deps: [USER_OPTIONS],
                },
            ],
        };
    }
}
ConfirmationPopoverModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
ConfirmationPopoverModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverModule, declarations: [ConfirmationPopoverDirective,
        ConfirmationPopoverWindowComponent,
        FocusDirective], imports: [CommonModule], exports: [ConfirmationPopoverDirective, FocusDirective] });
ConfirmationPopoverModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverModule, imports: [CommonModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: ConfirmationPopoverModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [
                        ConfirmationPopoverDirective,
                        ConfirmationPopoverWindowComponent,
                        FocusDirective,
                    ],
                    imports: [CommonModule],
                    exports: [ConfirmationPopoverDirective, FocusDirective]
                }]
        }] });
/*
 * Public API Surface of angular-confirmation-popover
 */
/**
 * Generated bundle index. Do not edit.
 */
export { ConfirmationPopoverDirective, ConfirmationPopoverModule, FocusDirective };
//# sourceMappingURL=angular-confirmation-popover.mjs.map