import { __decorate, __param, __awaiter } from 'tslib';
import { ElementRef, HostListener, Component, ChangeDetectionStrategy, ViewEncapsulation, Optional, Host, Input, Directive, InjectionToken, EventEmitter, ViewChild, Output, forwardRef, ContentChild, Self, HostBinding, Inject, TemplateRef, ViewContainerRef, Renderer2, ChangeDetectorRef, NgZone, Pipe, NgModule } from '@angular/core';
import { trigger, transition, style, animate } from '@angular/animations';
import { BehaviorSubject, fromEvent, merge, EMPTY, combineLatest, of } from 'rxjs';
import { mixinDisabled, mixinGrouped, ImageConverter, mixinFocused, mixinReadonly, mixinRequired, mixinError, mixinHideErrors, coerceBooleanProperty, Platform, mixinLoad } from '@bravobit/bb-foundation';
import { NG_VALUE_ACCESSOR, NgControl, FormGroupDirective } from '@angular/forms';
import { map, mapTo, startWith, distinctUntilChanged, share, tap, delay } from 'rxjs/operators';
import { LocalizeModule } from '@bravobit/bb-foundation/localize';
import { DomSanitizer } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';

let BbDropdown = class BbDropdown {
    constructor(_elementRef) {
        this._elementRef = _elementRef;
        // State.
        this.visible$ = new BehaviorSubject(false);
    }
    toggle() {
        return this.visible$.next(!this.visible$.getValue());
    }
    close() {
        return this.visible$.next(false);
    }
    onDocumentClick(target) {
        if (!target) {
            return;
        }
        if (this._elementRef.nativeElement.contains(target)) {
            return;
        }
        return this.close();
    }
};
BbDropdown.ctorParameters = () => [
    { type: ElementRef }
];
__decorate([
    HostListener('document:click', ['$event.target'])
], BbDropdown.prototype, "onDocumentClick", null);
BbDropdown = __decorate([
    Component({
        selector: 'bb-dropdown',
        template: "<button (click)=\"toggle()\"\n        [class.opened]=\"visible$ | async\"\n        type=\"button\">\n    <ng-content></ng-content>\n</button>\n\n<div *ngIf=\"visible$ | async\"\n     [@dropdownMenuAnimation]=\"true\"\n     class=\"bb-dropdown-menu\"\n     role=\"list\">\n    <ng-content select=\"[bbDropdownItem], hr\"></ng-content>\n</div>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: { 'class': 'bb-dropdown' },
        preserveWhitespaces: false,
        animations: [
            trigger('dropdownMenuAnimation', [
                transition(':enter', [
                    // 1. Set the initial state.
                    style({ opacity: 0, transform: 'scale(0.9)' }),
                    // 2. Start the animation to show the item.
                    animate('80ms cubic-bezier(0, 0, .2, 1)', style({ opacity: 1, transform: 'scale(1)' }))
                ]),
                transition(':leave', [
                    // 1. Set the initial state.
                    style({ opacity: 1, transform: 'scale(1)' }),
                    // 2. Start the animation to hide the item.
                    animate('80ms cubic-bezier(0, 0, .2, 1)', style({ opacity: 0, transform: 'scale(0.9)' }))
                ])
            ])
        ],
        styles: [".bb-dropdown{position:relative;display:inline-block}.bb-dropdown.right>.bb-dropdown-menu{right:0;left:auto;-webkit-transform-origin:top right;-ms-transform-origin:top right;transform-origin:top right}.bb-dropdown-menu{left:0;top:100%;padding:0;z-index:10;display:block;margin:10px 0 0;border-radius:4px;position:absolute;list-style-type:none;background-color:#fff;border:1px solid #ccc;-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;box-shadow:0 0 6px 0 rgba(0,0,0,.1)}.bb-dropdown-menu:after{width:0;top:-5px;height:0;right:5px;content:\"\";position:absolute;border-style:solid;border-width:0 10px 5px;border-color:transparent transparent #d9d9d9}.bb-dropdown-menu>hr{margin:0;height:1px;border:none;background-color:#ccc}.bb-dropdown-item{width:100%;border:none;line-height:1;display:block;cursor:pointer;text-align:left;font-weight:500;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:12px 20px;white-space:nowrap;text-decoration:none;color:#676767!important;background-color:transparent;-webkit-transition:background-color 250ms cubic-bezier(0,0,.2,1);transition:background-color 250ms cubic-bezier(0,0,.2,1)}.bb-dropdown-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.bb-dropdown-item:hover{background-color:#f6f6f6}.bb-dropdown-item:focus{box-shadow:0 0 0 3px rgba(220,224,233,.5)}.bb-dropdown-item:active{background-color:#f0f0f0}"]
    })
], BbDropdown);
let BbDropdownItem = class BbDropdownItem {
    constructor(_parent) {
        this._parent = _parent;
        // Inputs.
        this.closeOnClick = true;
    }
    onClick() {
        if (!this.closeOnClick) {
            return;
        }
        this._parent && this._parent.close();
    }
};
BbDropdownItem.ctorParameters = () => [
    { type: BbDropdown, decorators: [{ type: Optional }, { type: Host }] }
];
__decorate([
    Input()
], BbDropdownItem.prototype, "closeOnClick", void 0);
__decorate([
    HostListener('click')
], BbDropdownItem.prototype, "onClick", null);
BbDropdownItem = __decorate([
    Directive({
        selector: '[bbDropdownItem]',
        host: { 'class': 'bb-dropdown-item' }
    }),
    __param(0, Optional()), __param(0, Host())
], BbDropdownItem);

const ELEMENTS_ICONS = new InjectionToken('elements_icons');
const ELEMENTS_ERRORS = new InjectionToken('elements_errors');

var BbImagePicker_1;
class BbImagePickerBase {
}
const BbImagePickerMixinBase = mixinDisabled(mixinGrouped(BbImagePickerBase));
let BbImagePicker = BbImagePicker_1 = class BbImagePicker extends BbImagePickerMixinBase {
    constructor(_converter) {
        super();
        this._converter = _converter;
        // Inputs.
        this.label = null;
        this.placeholder = null;
        this.styleDimensions = null;
        this.cropDimensions = null;
        // Form.
        this._value$ = new BehaviorSubject(null);
        this.valueChange = new EventEmitter();
        this.onTouchedCallback = () => {
        };
        this.onChangeCallback = () => {
        };
    }
    get value() {
        return this._value$.getValue();
    }
    set value(value) {
        this._value$.next(value);
        this.valueChange.emit(value);
    }
    get image() {
        return this._value$.pipe(map(value => value || this.placeholder), map(value => value ? `url(${value})` : null));
    }
    onFileChange(event) {
        return __awaiter(this, void 0, void 0, function* () {
            // Grab the file from the event.
            const file = event.target.files[0];
            // Check if the file exists.
            if (!file || this.disabled) {
                return;
            }
            try {
                this.value = yield this._converter.toDataUri(file, this.cropDimensions);
            }
            catch (error) {
                this.value = null;
            }
            this.onChangeCallback(this.value);
            if (this.fileInput && this.fileInput.nativeElement) {
                this.fileInput.nativeElement.value = '';
            }
        });
    }
    openFilePicker() {
        if (this.disabled) {
            return;
        }
        // Execute a click on the file input.
        this.fileInput
            && this.fileInput.nativeElement
            && this.fileInput.nativeElement.click
            && this.fileInput.nativeElement.click();
    }
    writeValue(value) {
        this.value = value;
    }
    registerOnChange(method) {
        this.onChangeCallback = method;
    }
    registerOnTouched(method) {
        this.onTouchedCallback = method;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
};
BbImagePicker.ctorParameters = () => [
    { type: ImageConverter }
];
__decorate([
    ViewChild('fileInput', { static: true })
], BbImagePicker.prototype, "fileInput", void 0);
__decorate([
    Input()
], BbImagePicker.prototype, "label", void 0);
__decorate([
    Input()
], BbImagePicker.prototype, "placeholder", void 0);
__decorate([
    Input()
], BbImagePicker.prototype, "styleDimensions", void 0);
__decorate([
    Input()
], BbImagePicker.prototype, "cropDimensions", void 0);
__decorate([
    Input()
], BbImagePicker.prototype, "value", null);
__decorate([
    Output()
], BbImagePicker.prototype, "valueChange", void 0);
BbImagePicker = BbImagePicker_1 = __decorate([
    Component({
        selector: 'bb-image-picker',
        template: "<!-- The input that can open the file picker. -->\n<input #fileInput\n       (change)=\"onFileChange($event)\"\n       class=\"bb-image-picker-input\"\n       type=\"file\"\n       tabindex=\"-1\"\n       accept=\"image/*\">\n\n<span [style.width]=\"styleDimensions?.width || '100%'\"\n      [style.height]=\"styleDimensions?.height || '215px'\"\n      [style.background-image]=\"image | async\"\n      class=\"bb-image-input-image\">\n    </span>\n\n<button *ngIf=\"label as labelText\"\n        (click)=\"openFilePicker()\"\n        bb-button\n        class=\"bb-image-input-button\"\n        type=\"button\">\n    {{ labelText }}\n</button>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: {
            'class': 'bb-image-picker',
            '[class.disabled]': 'disabled',
            '[class.grouped]': 'grouped'
        },
        inputs: ['grouped', 'disabled'],
        providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => BbImagePicker_1), multi: true }],
        preserveWhitespaces: false,
        styles: [".bb-image-picker{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.bb-image-picker.circle>.bb-image-input-image{border-radius:50%}.bb-image-picker.grouped{margin-bottom:20px}.bb-image-picker.disabled{opacity:.5;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.bb-image-picker-input{opacity:0;z-index:-1;width:.1px;height:.1px;overflow:hidden;position:absolute}.bb-image-input-image{display:-webkit-box;display:-ms-flexbox;display:flex;cursor:default;position:relative;border-radius:4px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) center center/cover no-repeat rgba(0,0,0,.2)}.bb-image-input-button{margin-top:10px}"]
    })
], BbImagePicker);

let nextUniqueId = 0;
class BbFormControlBase {
}
const BbFormControlMixinBase = mixinDisabled(mixinFocused(mixinReadonly(mixinGrouped(mixinRequired(mixinError(mixinHideErrors(BbFormControlBase)))))));
let BbFormControl = class BbFormControl extends BbFormControlMixinBase {
    constructor() {
        super(...arguments);
        // Inputs.
        this.label = null;
        this.hint = null;
        // Data.
        this.arrow = false;
        // Data.
        this.labelId = `bb-form-control-${nextUniqueId++}`;
    }
    onErrorChange(error) {
        this.error = !!error;
    }
};
__decorate([
    ContentChild(NgControl)
], BbFormControl.prototype, "ngControl", void 0);
__decorate([
    Input()
], BbFormControl.prototype, "label", void 0);
__decorate([
    Input()
], BbFormControl.prototype, "hint", void 0);
BbFormControl = __decorate([
    Component({
        selector: 'bb-form-control',
        template: "<!-- Label of the form control. -->\n<label *ngIf=\"label as labelContent\"\n       [attr.for]=\"labelId\"\n       class=\"bb-form-control-label\">\n    <ng-template [bbTemplate]=\"labelContent\">\n        {{ labelContent }}\n    </ng-template>\n</label>\n\n<!-- The input with the addons. -->\n<div class=\"bb-form-control-container\">\n    <ng-content select=\"[bbPrefix]\"></ng-content>\n    <ng-content select=\"[bbInput]\"></ng-content>\n    <ng-content select=\"[bbSuffix]\"></ng-content>\n</div>\n\n<!-- The error component. -->\n<bb-form-error *ngIf=\"!hideErrors\"\n               [control]=\"ngControl\"\n               (errorChange)=\"onErrorChange($event)\">\n</bb-form-error>\n\n<!-- The form control hint. -->\n<p *ngIf=\"hint as hintContent\"\n   class=\"bb-form-control-hint\">\n    <ng-template [bbTemplate]=\"hintContent\">\n        {{ hintContent }}\n    </ng-template>\n</p>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: {
            'class': 'bb-form-control',
            '[class.readonly]': 'readonly',
            '[class.required]': 'required',
            '[class.disabled]': 'disabled',
            '[class.focused]': 'focused',
            '[class.grouped]': 'grouped',
            '[class.arrow]': 'arrow',
            '[class.error]': 'error'
        },
        inputs: ['grouped', 'hideErrors'],
        preserveWhitespaces: false,
        styles: [".bb-form-control{color:#2d3c4d;display:block}.bb-form-control>.bb-form-control-container>.bb-prefix,.bb-form-control>.bb-form-control-container>.bb-suffix{margin:0 8px;color:#b4b4b4;-webkit-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control.grouped{margin-bottom:20px}.bb-form-control.small{max-width:240px}.bb-form-control.medium{max-width:480px}.bb-form-control.large{max-width:720px}.bb-form-control.required>.bb-form-control-label:after{content:\"*\";color:#c23934;font-size:12px;line-height:1.5}.bb-form-control.disabled>.bb-form-control-container{cursor:default;pointer-events:none;background-color:rgba(204,204,204,.64)}.bb-form-control.disabled>.bb-form-control-container>input,.bb-form-control.disabled>.bb-form-control-container>select,.bb-form-control.disabled>.bb-form-control-container>textarea{color:#aaa}.bb-form-control.readonly>.bb-form-control-container{cursor:default;border:1px dotted #bdc4c9}.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container{background-color:#fff;box-shadow:inset 0 3px 0 0 rgba(183,188,194,.2),0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(0,123,255,.2)}.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>input::-webkit-input-placeholder,.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>textarea::-webkit-input-placeholder{color:#b4b4b4;-webkit-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>input::-moz-placeholder,.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>textarea::-moz-placeholder{color:#b4b4b4;-moz-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>input:-ms-input-placeholder,.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>textarea:-ms-input-placeholder{color:#b4b4b4;-ms-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>input::-ms-input-placeholder,.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>textarea::-ms-input-placeholder{color:#b4b4b4;-ms-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>input::placeholder,.bb-form-control:not(.disabled):not(.readonly).focused>.bb-form-control-container>textarea::placeholder{color:#b4b4b4;-webkit-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control.error>.bb-form-control-label{color:#c23934}.bb-form-control.error>.bb-form-control-hint{display:none}.bb-form-control.error>.bb-form-control-container{border:1px solid #962b26;background-color:rgba(194,57,52,.25)!important;box-shadow:inset 0 3px 0 0 rgba(183,188,194,.2),0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(194,57,52,.4)!important}.bb-form-control.error>.bb-form-control-container>.bb-prefix,.bb-form-control.error>.bb-form-control-container>.bb-suffix{color:#c23934}.bb-form-control.error>.bb-form-control-container>input::-webkit-input-placeholder,.bb-form-control.error>.bb-form-control-container>textarea::-webkit-input-placeholder{color:rgba(194,57,52,.4)!important}.bb-form-control.error>.bb-form-control-container>input::-moz-placeholder,.bb-form-control.error>.bb-form-control-container>textarea::-moz-placeholder{color:rgba(194,57,52,.4)!important}.bb-form-control.error>.bb-form-control-container>input:-ms-input-placeholder,.bb-form-control.error>.bb-form-control-container>textarea:-ms-input-placeholder{color:rgba(194,57,52,.4)!important}.bb-form-control.error>.bb-form-control-container>input::-ms-input-placeholder,.bb-form-control.error>.bb-form-control-container>textarea::-ms-input-placeholder{color:rgba(194,57,52,.4)!important}.bb-form-control.error>.bb-form-control-container>input::placeholder,.bb-form-control.error>.bb-form-control-container>textarea::placeholder{color:rgba(194,57,52,.4)!important}.bb-form-control.arrow>.bb-form-control-container:after{width:20px;content:\"\";height:36px;display:-webkit-box;display:-ms-flexbox;display:flex;min-width:20px;background-repeat:no-repeat;background-position:calc(100% - 8px) center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAGCAYAAAAYLBS/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAWUlEQVQYlY3QsQ2DMAAEwMMTsAkrZInvWY3WXiIjJJtkA1OBRCIRf/nSffFTrXXGE4uxbCXJBw+8R0CStcAg3JKsUI7mDzzBBd3AC4Cp9/4z21o7znl9A9gBAf4fpjLTwkUAAAAASUVORK5CYII=)}.bb-form-control-container{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;overflow:hidden;position:relative;border-radius:3px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid #b6bbc1;background-color:#fff8ff;-webkit-transition-duration:250ms;transition-duration:250ms;-webkit-transition-property:background-color,box-shadow;transition-property:background-color,box-shadow;-webkit-transition-timing-function:cubic-bezier(0,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);box-shadow:inset 0 3px 0 0 rgba(183,188,194,.2),0 6px 6px -6px rgba(0,0,0,.1)}.bb-form-control-container>input::-webkit-input-placeholder,.bb-form-control-container>textarea::-webkit-input-placeholder{color:#d2d2d2;-webkit-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control-container>input::-moz-placeholder,.bb-form-control-container>textarea::-moz-placeholder{color:#d2d2d2;-moz-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control-container>input:-ms-input-placeholder,.bb-form-control-container>textarea:-ms-input-placeholder{color:#d2d2d2;-ms-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control-container>input::-ms-input-placeholder,.bb-form-control-container>textarea::-ms-input-placeholder{color:#d2d2d2;-ms-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control-container>input::placeholder,.bb-form-control-container>textarea::placeholder{color:#d2d2d2;-webkit-transition:color .3s cubic-bezier(0,0,.2,1);transition:color .3s cubic-bezier(0,0,.2,1)}.bb-form-control-container>input,.bb-form-control-container>select,.bb-form-control-container>textarea{margin:0;width:100%;border:none;color:#3d464d;font-size:16px;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.bb-form-control-container>input,.bb-form-control-container>select{height:36px;padding:0 8px}.bb-form-control-container>select::-ms-expand{display:none}.bb-form-control-container>input::-ms-clear,.bb-form-control-container>input::-ms-reveal{width:0;height:0;display:none}.bb-form-control-container>input::-webkit-search-cancel-button,.bb-form-control-container>input::-webkit-search-decoration,.bb-form-control-container>input::-webkit-search-results-button,.bb-form-control-container>input::-webkit-search-results-decoration{display:none}.bb-form-control-container>textarea{resize:none;padding:8px}.bb-form-control-label{color:#000;display:block;position:relative;margin-bottom:4px;-webkit-transition:color 30ms cubic-bezier(0,0,.2,1);transition:color 30ms cubic-bezier(0,0,.2,1)}.bb-form-control-error,.bb-form-control-hint{display:block;font-size:13px;margin-top:4px}.bb-form-control-error{color:#c23934}.bb-form-control-hint{color:#738694}"]
    })
], BbFormControl);

var BbFilePicker_1;
let nextUniqueId$1 = 0;
class BbFilePickerBase {
}
const BbFilePickerMixinBase = mixinRequired(mixinDisabled(mixinGrouped(mixinError(mixinHideErrors(BbFilePickerBase)))));
let BbFilePicker = BbFilePicker_1 = class BbFilePicker extends BbFilePickerMixinBase {
    constructor() {
        super(...arguments);
        // Inputs.
        this.label = null;
        this.hint = null;
        this.accept = null;
        this.showImages = true;
        this.allowDragging = true;
        // State.
        this.labelId = `bb-file-picker-${nextUniqueId$1++}`;
        this.hovered = false;
        this.value$ = new BehaviorSubject({});
        this.valueChange = new EventEmitter();
        this.onTouchedCallback = () => {
        };
        this.onChangeCallback = () => {
        };
        this.saveFile = (files) => {
            // Validate the files exist.
            if (!files) {
                return;
            }
            // Retrieve the first file.
            const file = files[0];
            // Validate the first file exists.
            if (!file) {
                return;
            }
            // Save the file.
            this.value = file;
        };
        this.getFileListFromEvent = (event) => {
            const element = event.target;
            if (!element) {
                return null;
            }
            return element.files;
        };
        this.preventDefault = (event) => {
            event.preventDefault();
            event.stopPropagation();
        };
    }
    get value() {
        const { file } = this.value$.getValue();
        return file;
    }
    set value(value) {
        this.value$.next({ file: value });
        this.valueChange.emit(value);
    }
    onDrag(event, isHovered) {
        // Validate the input can support drag.
        if (!this.allowDragging || this.disabled) {
            return;
        }
        // Prevent the default event action
        // and start the hovering.
        this.preventDefault(event);
        this.hovered = isHovered;
    }
    onDrop(event) {
        // Validate the input can support drag.
        if (!this.allowDragging || this.disabled) {
            return;
        }
        // Prevent the default event action
        // and stop the hovering.
        this.preventDefault(event);
        this.hovered = false;
        // Save the file.
        this.saveFile(event['dataTransfer'].files);
        // Run the on change callback.
        this.onChangeCallback(this.value);
    }
    onButtonPressed(file) {
        if (file) {
            this.value = null;
            this.onChangeCallback(this.value);
            return;
        }
        return this.openFilePicker();
    }
    openFilePicker() {
        return this.fileInput
            && this.fileInput.nativeElement
            && this.fileInput.nativeElement.click
            && this.fileInput.nativeElement.click();
    }
    onFileChange(event) {
        // Validate the input is not disabled.
        if (this.disabled) {
            return;
        }
        // Extract the file from the event.
        const fileList = this.getFileListFromEvent(event);
        // Save the file.
        this.saveFile(fileList);
        // Run the on change callback.
        this.onChangeCallback(this.value);
        // Clear the file input.
        if (this.fileInput && this.fileInput.nativeElement) {
            this.fileInput.nativeElement.value = '';
        }
    }
    writeValue(value) {
        this.value = value;
    }
    registerOnChange(method) {
        this.onChangeCallback = method;
    }
    registerOnTouched(method) {
        this.onTouchedCallback = method;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
    }
    onErrorChange(error) {
        this.error = !!error;
    }
};
__decorate([
    ViewChild('fileInput', { static: true })
], BbFilePicker.prototype, "fileInput", void 0);
__decorate([
    ContentChild('extra')
], BbFilePicker.prototype, "extraTemplate", void 0);
__decorate([
    Input()
], BbFilePicker.prototype, "label", void 0);
__decorate([
    Input()
], BbFilePicker.prototype, "hint", void 0);
__decorate([
    Input()
], BbFilePicker.prototype, "accept", void 0);
__decorate([
    Input()
], BbFilePicker.prototype, "showImages", void 0);
__decorate([
    Input()
], BbFilePicker.prototype, "allowDragging", void 0);
__decorate([
    Input()
], BbFilePicker.prototype, "value", null);
__decorate([
    Output()
], BbFilePicker.prototype, "valueChange", void 0);
__decorate([
    HostListener('dragover', ['$event', 'true']),
    HostListener('dragleave', ['$event', 'false'])
], BbFilePicker.prototype, "onDrag", null);
__decorate([
    HostListener('drop', ['$event'])
], BbFilePicker.prototype, "onDrop", null);
BbFilePicker = BbFilePicker_1 = __decorate([
    Component({
        selector: 'bb-file-picker',
        template: "<!-- The label of the input. -->\n<label *ngIf=\"label as labelContent\"\n       [for]=\"labelId\"\n       class=\"bb-file-picker-label\">\n    <ng-template [bbTemplate]=\"labelContent\">\n        {{ labelContent }}\n    </ng-template>\n</label>\n\n<!-- The input that can open the file picker. -->\n<input #fileInput\n       [accept]=\"accept\"\n       [disabled]=\"disabled\"\n       (change)=\"onFileChange($event)\"\n       class=\"bb-file-picker-input\"\n       type=\"file\"\n       tabindex=\"-1\">\n\n<div *ngIf=\"value$ | async as data\"\n     class=\"bb-file-picker-wrapper\">\n    <!-- The button that accepts files. -->\n    <div class=\"bb-file-picker-container\">\n        <button [class.destructive]=\"!!data?.file\"\n                [class.standalone]=\"!allowDragging\"\n                [disabled]=\"disabled\"\n                [id]=\"labelId\"\n                (click)=\"onButtonPressed(data?.file)\"\n                type=\"button\"\n                class=\"bb-file-picker-button\">\n            <ng-container *ngTemplateOutlet=\"data?.file ? closeIcon : uploadIcon\"></ng-container>\n            {{ (data?.file ? 'file-picker.remove' : 'file-picker.choose') | bbLocalize }}\n        </button>\n        <div *ngIf=\"allowDragging\"\n             class=\"bb-file-picker-zone\">\n            {{ 'file-picker.drop' | bbLocalize }}\n        </div>\n    </div>\n\n    <ng-container *ngIf=\"!!extraTemplate\">\n        <ng-container *ngTemplateOutlet=\"extraTemplate; context: {$implicit: data?.file}\"></ng-container>\n    </ng-container>\n\n    <ng-container *ngIf=\"showImages\">\n        <div *ngIf=\"data?.file | bbFileImage | async as image\"\n             class=\"bb-file-picker-image-container\">\n            <div class=\"bb-file-picker-image-wrapper\">\n                <div [@bbFilePickerImageAnimation]=\"true\"\n                     [style.padding-top.%]=\"image?.aspectRatio * 100\"\n                     [style.background-image]=\"image?.background\"\n                     class=\"bb-file-picker-image\">\n                </div>\n            </div>\n        </div>\n    </ng-container>\n\n    <!-- Extra information of the file. -->\n    <div [class.visible]=\"!!data?.file\"\n         class=\"bb-file-picker-info\">\n        <span *ngIf=\"data?.file?.name as name\">{{ name }}</span>\n        <span *ngIf=\"data?.file?.size as size\">{{ size | bbFileSize }}</span>\n    </div>\n</div>\n\n<bb-form-error *ngIf=\"!hideErrors\"\n               (errorChange)=\"onErrorChange($event)\">\n</bb-form-error>\n\n<!-- The file picker hint. -->\n<p *ngIf=\"hint as hintContent\"\n   class=\"bb-file-picker-hint\">\n    <ng-template [bbTemplate]=\"hintContent\">\n        {{ hintContent }}\n    </ng-template>\n</p>\n\n<!-- Upload icon. -->\n<ng-template #uploadIcon>\n    <svg xmlns=\"http://www.w3.org/2000/svg\"\n         class=\"bb-file-picker-icon\"\n         width=\"24\"\n         height=\"24\">\n        <path fill=\"currentColor\"\n              d=\"M2 12.5C2 9.46 4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.79 4-4 4H9.5a2.5 2.5 0 010-5H17v2H9.41c-.55 0-.55 1 0 1H18c1.1 0 2-.9 2-2s-.9-2-2-2H7.5C5.57 9 4 10.57 4 12.5S5.57 16 7.5 16H17v2H7.5C4.46 18 2 15.54 2 12.5z\"></path>\n        <path fill=\"none\" d=\"M0 0h24v24H0V0z\"></path>\n    </svg>\n</ng-template>\n\n<!-- Close icon. -->\n<ng-template #closeIcon>\n    <svg xmlns=\"http://www.w3.org/2000/svg\"\n         class=\"bb-file-picker-icon\"\n         width=\"24\"\n         height=\"24\">\n        <path fill=\"currentColor\"\n              d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"></path>\n        <path d=\"M0 0h24v24H0z\" fill=\"none\"></path>\n    </svg>\n</ng-template>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => BbFilePicker_1),
                multi: true
            }
        ],
        host: {
            'class': 'bb-file-picker',
            '[class.required]': 'required',
            '[class.disabled]': 'disabled',
            '[class.grouped]': 'grouped',
            '[class.hovered]': 'hovered',
            '[class.error]': 'error'
        },
        animations: [
            trigger('bbFilePickerImageAnimation', [
                transition(':enter', [
                    style({ opacity: 0 }),
                    animate('200ms', style({ opacity: 1 }))
                ]),
                transition(':leave', [
                    animate('200ms', style({ opacity: 0 }))
                ])
            ])
        ],
        inputs: ['disabled', 'hideErrors', 'grouped', 'required'],
        preserveWhitespaces: false,
        styles: [".bb-file-picker{display:block}.bb-file-picker.disabled>.bb-file-picker-wrapper{cursor:default;background-color:rgba(204,204,204,.64)}.bb-file-picker.grouped{margin-bottom:20px}.bb-file-picker.full>.bb-file-picker-wrapper{width:100%}.bb-file-picker:not(.disabled) .bb-file-picker-button{background-color:#fff}.bb-file-picker:not(.disabled).hovered>.bb-file-picker-wrapper,.bb-file-picker:not(.disabled):focus>.bb-file-picker-wrapper{box-shadow:inset 0 3px 0 0 rgba(183,188,194,.2),0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(0,123,255,.2)}.bb-file-picker.required>.bb-file-picker-label:after{content:\"*\";color:#c23934;font-size:12px;line-height:1.5}.bb-file-picker.error>.bb-file-picker-label{color:#c23934}.bb-file-picker.error>.bb-file-picker-hint{display:none}.bb-file-picker.error>.bb-file-picker-wrapper{border:1px solid #962b26;background-color:rgba(194,57,52,.25)!important;box-shadow:inset 0 3px 0 0 rgba(183,188,194,.2),0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(194,57,52,.4)!important}.bb-file-picker.error .bb-file-picker-button{background-color:transparent}.bb-file-picker-wrapper{max-width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-radius:3px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;border:1px solid #b6bbc1;background-color:#fff8ff;-webkit-transition:box-shadow .2s cubic-bezier(0,0,.2,1);transition:box-shadow .2s cubic-bezier(0,0,.2,1);box-shadow:inset 0 3px 0 0 rgba(183,188,194,.2),0 6px 6px -6px rgba(0,0,0,.1)}.bb-file-picker-label{color:#000;display:block;position:relative;margin-bottom:4px}.bb-file-picker-input{opacity:0;z-index:-1;width:.1px;height:.1px;overflow:hidden;position:absolute}.bb-file-picker-container{min-height:38px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.bb-file-picker-button{margin:0;z-index:1;border:none;color:#2196f3;line-height:1;cursor:pointer;padding:0 12px;-webkit-appearance:none;-moz-appearance:none;appearance:none;font-weight:500;-webkit-box-align:center;-ms-flex-align:center;align-items:center;white-space:nowrap;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;border-top-left-radius:3px;border-bottom-left-radius:3px;border-right:1px solid #b6bbc1;background-color:rgba(255,255,255,.5);-webkit-transition:box-shadow .2s cubic-bezier(0,0,.2,1);transition:box-shadow .2s cubic-bezier(0,0,.2,1)}.bb-file-picker-button:focus{box-shadow:0 0 0 3px rgba(0,123,255,.2)}.bb-file-picker-button:disabled{cursor:default}.bb-file-picker-button.destructive{color:#f55656}.bb-file-picker-button.standalone{width:100%;border-right:none;border-top-right-radius:3px;border-bottom-right-radius:3px}.bb-file-picker-icon{margin-right:4px}.bb-file-picker-zone{-webkit-box-flex:1;-ms-flex:1;flex:1;color:#848f99;font-size:14px;padding:8px 12px;line-height:18px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.bb-file-picker-info{height:0;color:#848f99;padding:0 12px;overflow:hidden;line-height:36px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;background-color:#fff8ff;border-top:0 solid #b6bbc1;-webkit-transition:height .2s cubic-bezier(0,0,.2,1);transition:height .2s cubic-bezier(0,0,.2,1)}.bb-file-picker-info.visible{height:38px;border-top-width:1px}.bb-file-picker-info>span{opacity:.4;max-width:100%;font-size:14px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.bb-file-picker-info>span:first-child{-webkit-box-flex:1;-ms-flex:1;flex:1}.bb-file-picker-info>span:last-child{margin-left:12px}.bb-file-picker-image-container{overflow:hidden;border-top:1px solid #b6bbc1}.bb-file-picker-image-wrapper{width:100%;max-width:40%;margin:20px auto}.bb-file-picker-image{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;overflow:hidden;position:relative;border-radius:4px;will-change:opacity;background-size:cover;background-position:center;background-repeat:no-repeat}.bb-file-picker-hint{display:block;color:#738694;font-size:13px;margin-top:4px}"]
    })
], BbFilePicker);

let BbSuffix = class BbSuffix {
};
BbSuffix = __decorate([
    Directive({
        selector: '[bbSuffix]',
        host: {
            'class': 'bb-suffix'
        }
    })
], BbSuffix);
let BbPrefix = class BbPrefix {
};
BbPrefix = __decorate([
    Directive({
        selector: '[bbPrefix]',
        host: {
            'class': 'bb-prefix'
        }
    })
], BbPrefix);

let BbFormSubmit = class BbFormSubmit {
    constructor(_host, _formDirective) {
        this._host = _host;
        this._formDirective = _formDirective;
    }
    ngOnInit() {
        // Submit changes.
        const regularSubmitChanges$ = fromEvent(this.nativeElement, 'submit').pipe(mapTo(true));
        // Reactive form submit changes.
        const reactiveSubmitChanges$ = this.reactiveSubmitChanges();
        // Reset changes.
        const resetChanges$ = fromEvent(this.nativeElement, 'reset').pipe(mapTo(false));
        // Listen to the submit status.
        this.submitStatus$ = merge(regularSubmitChanges$, reactiveSubmitChanges$, resetChanges$).pipe(startWith(false), distinctUntilChanged(), share());
    }
    submit() {
        this._formDirective && this._formDirective.ngSubmit.emit();
    }
    reset() {
        return this.nativeElement.reset();
    }
    get nativeElement() {
        return this._host && this._host.nativeElement;
    }
    reactiveSubmitChanges() {
        if (!this._formDirective) {
            return EMPTY;
        }
        return this._formDirective.ngSubmit.pipe(mapTo(true));
    }
};
BbFormSubmit.ctorParameters = () => [
    { type: ElementRef },
    { type: FormGroupDirective, decorators: [{ type: Optional }, { type: Self }] }
];
BbFormSubmit = __decorate([
    Directive({
        selector: 'form',
        exportAs: 'bbForm'
    }),
    __param(1, Optional()), __param(1, Self())
], BbFormSubmit);

let BbSelect = class BbSelect {
    constructor(_elementRef, _ngControl, _formControl) {
        this._elementRef = _elementRef;
        this._ngControl = _ngControl;
        this._formControl = _formControl;
        this.hasArrow = true;
        this._disabled = false;
        this._required = false;
    }
    ngOnInit() {
        // Set an arrow on the form control if
        // it requires one.
        this._formControl.arrow = this.hasArrow;
    }
    ngDoCheck() {
        if (this._ngControl) {
            this.disabled = this._ngControl.disabled;
        }
    }
    ngOnDestroy() {
        this._subscription && this._subscription.unsubscribe();
    }
    focus() {
        return this._elementRef
            && this._elementRef.nativeElement
            && this._elementRef.nativeElement.focus
            && this._elementRef.nativeElement.focus();
    }
    setFocus(hasFocus) {
        if (!this._formControl) {
            return;
        }
        this._formControl.focused = hasFocus;
    }
    get id() {
        return this._formControl && this._formControl.labelId;
    }
    get disabled() {
        if (this._ngControl && this._ngControl.disabled !== null) {
            return this._ngControl.disabled;
        }
        return this._disabled;
    }
    set disabled(newValue) {
        this._disabled = coerceBooleanProperty(newValue);
        if (!this._formControl) {
            return;
        }
        this._formControl.disabled = this._disabled;
    }
    get required() {
        return this._required;
    }
    set required(newValue) {
        this._required = coerceBooleanProperty(newValue);
        if (!this._formControl) {
            return;
        }
        this._formControl.required = this._required;
    }
};
BbSelect.ctorParameters = () => [
    { type: ElementRef },
    { type: NgControl, decorators: [{ type: Optional }, { type: Self }] },
    { type: BbFormControl, decorators: [{ type: Optional }, { type: Host }] }
];
__decorate([
    HostBinding('attr.id')
], BbSelect.prototype, "id", null);
__decorate([
    Input()
], BbSelect.prototype, "disabled", null);
__decorate([
    Input()
], BbSelect.prototype, "required", null);
BbSelect = __decorate([
    Directive({
        selector: 'select[bbInput]',
        host: {
            '[disabled]': 'disabled',
            '(focus)': 'setFocus(true)',
            '(blur)': 'setFocus(false)'
        }
    }),
    __param(1, Optional()), __param(1, Self()),
    __param(2, Optional()), __param(2, Host())
], BbSelect);
let BbInput = class BbInput extends BbSelect {
    constructor(_elementRef, _ngControl, _formControl) {
        super(_elementRef, _ngControl, _formControl);
        this._elementRef = _elementRef;
        this._ngControl = _ngControl;
        this._formControl = _formControl;
        this.hasArrow = false;
        this._readonly = false;
    }
    get readonly() {
        return this._readonly;
    }
    set readonly(newValue) {
        this._readonly = coerceBooleanProperty(newValue);
        if (!this._formControl) {
            return;
        }
        this._formControl.readonly = this._readonly;
    }
};
BbInput.ctorParameters = () => [
    { type: ElementRef },
    { type: NgControl, decorators: [{ type: Optional }, { type: Self }] },
    { type: BbFormControl, decorators: [{ type: Optional }, { type: Host }] }
];
__decorate([
    Input()
], BbInput.prototype, "readonly", null);
BbInput = __decorate([
    Directive({
        selector: 'input[bbInput], textarea[bbInput]',
        host: {
            '[disabled]': 'disabled',
            '[readonly]': 'readonly',
            '(focus)': 'setFocus(true)',
            '(blur)': 'setFocus(false)'
        }
    }),
    __param(1, Optional()), __param(1, Self()),
    __param(2, Optional()), __param(2, Host())
], BbInput);

class BbFormGroupBase {
}
const BbFormGroupMixinBase = mixinGrouped(BbFormGroupBase);
let BbFormGroup = class BbFormGroup extends BbFormGroupMixinBase {
};
BbFormGroup = __decorate([
    Component({
        selector: 'bb-form-group',
        template: "<ng-content></ng-content>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: {
            'class': 'bb-form-group',
            '[class.grouped]': 'grouped'
        },
        inputs: ['grouped'],
        preserveWhitespaces: false,
        styles: [".bb-form-group{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:-10px}.bb-form-group>*{margin-top:10px}.bb-form-group>:not(:first-child){margin-left:10px}.bb-form-group.start{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.bb-form-group.end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.bb-form-group.vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:normal;-ms-flex-pack:normal;justify-content:normal}.bb-form-group.vertical>*{margin-left:0}.bb-form-group.vertical.start{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.bb-form-group.vertical.end{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.bb-form-group.grouped{margin-bottom:20px}"]
    })
], BbFormGroup);

let BbFormError = class BbFormError {
    constructor(_form, _control, _errors) {
        this._form = _form;
        this._control = _control;
        this._errors = _errors;
        // Outputs.
        this.errorChange = new EventEmitter();
    }
    // Inputs.
    set control(value) {
        this._ngControl = value;
    }
    get control() {
        return this._ngControl;
    }
    ngOnInit() {
        // Set the control if it was not set before.
        if (!this.control) {
            this.control = this._control;
        }
        // Listen for the submit changes
        const submitStatus$ = this.submitStatusChanges();
        // An observable that emits error changes.
        const errorChanges$ = this.statusChanges().pipe(map(() => this.getError(this.control.errors)), distinctUntilChanged(), map(error => typeof error === 'string' ? { token: error } : error));
        // Whenever the user submitted the form we want to
        // listen for any error changes.
        this.error$ = combineLatest([submitStatus$, errorChanges$]).pipe(map(([submitted, error]) => {
            // If not submitted return null.
            if (!submitted) {
                return null;
            }
            // Return the error if submitted.
            return error;
        }), tap(value => this.errorChange.emit(value)));
    }
    getError(errors) {
        // Validate the errors exist.
        if (!errors) {
            return null;
        }
        // Get the first error in the errors.
        const [errorName] = Object.keys(errors);
        const error = errors[errorName];
        // Validate the error exists.
        if (!error) {
            return null;
        }
        // Map the arrays into a object so we can
        // access the functions by a key-lookup.
        const errorFunctions = this._errors.reduce((previous, current) => (Object.assign(Object.assign({}, previous), current)), {});
        // Get the error function.
        const errorFunction = errorFunctions[errorName] || errorFunctions['unknown'];
        // Validate the error function exists.
        if (!errorFunction) {
            return null;
        }
        // Return the parsed error.
        return errorFunction(error);
    }
    submitStatusChanges() {
        if (!this._form) {
            return of(true);
        }
        return this._form.submitStatus$;
    }
    statusChanges() {
        if (!this.control) {
            return EMPTY;
        }
        return this.control.statusChanges.pipe(startWith(this.control.status), delay(0));
    }
};
BbFormError.ctorParameters = () => [
    { type: BbFormSubmit, decorators: [{ type: Optional }] },
    { type: NgControl, decorators: [{ type: Optional }] },
    { type: Array, decorators: [{ type: Optional }, { type: Inject, args: [ELEMENTS_ERRORS,] }] }
];
__decorate([
    Input()
], BbFormError.prototype, "control", null);
__decorate([
    Output()
], BbFormError.prototype, "errorChange", void 0);
BbFormError = __decorate([
    Component({
        selector: 'bb-form-error',
        template: "<ng-container *ngIf=\"error$ | async as error\">\n    <p *ngIf=\"error?.token | bbLocalize:{optional: true, data: error?.data} as message\"\n       class=\"bb-form-error-message\">\n        {{ message }}\n    </p>\n</ng-container>",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: {
            'class': 'bb-form-error'
        },
        preserveWhitespaces: false,
        styles: [".bb-form-error{display:block}.bb-form-error-message{color:#c23934;display:block;font-size:13px;margin-top:4px}"]
    }),
    __param(0, Optional()),
    __param(1, Optional()),
    __param(2, Optional()), __param(2, Inject(ELEMENTS_ERRORS))
], BbFormError);

let BbFocusTrap = class BbFocusTrap {
    constructor(_platform, _elementRef) {
        this._platform = _platform;
        this._elementRef = _elementRef;
        this._focusableElements = [
            'a[href]',
            'area[href]',
            'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
            'select:not([disabled]):not([aria-hidden])',
            'textarea:not([disabled]):not([aria-hidden])',
            'button:not([disabled]):not([aria-hidden])',
            'iframe',
            'object',
            'embed',
            '[contenteditable]',
            '[tabindex]:not([tabindex^="-"])'
        ];
        this.focus = (element) => {
            return element && element.focus && element.focus();
        };
        this.isTabEvent = (event) => {
            return event.key === 'Tab' || event.keyCode === 9;
        };
    }
    onKeydown(event) {
        // Validate it is a tab event.
        if (!this.isTabEvent(event)) {
            return;
        }
        // Trap the focus inside the element.
        return this.trapFocus(event);
    }
    trapFocus(event) {
        // Validate that the DOM is available.
        if (!this._platform.isBrowser) {
            return;
        }
        // Get all focusable nodes.
        const focusableNodes = this.getFocusableNodes();
        // Focus the first available element if the focus
        // is not in the modal.
        if (!this.element.contains(document.activeElement)) {
            return this.focus(focusableNodes[0]);
        }
        const focusedItemIndex = focusableNodes.indexOf(document.activeElement);
        if (event.shiftKey && focusedItemIndex === 0) {
            this.focus(focusableNodes[focusableNodes.length - 1]);
            return event.preventDefault();
        }
        if (!event.shiftKey && focusedItemIndex === focusableNodes.length - 1) {
            this.focus(focusableNodes[0]);
            return event.preventDefault();
        }
    }
    get element() {
        return this._elementRef.nativeElement;
    }
    getFocusableNodes() {
        const nodes = this.element.querySelectorAll(this._focusableElements);
        return Array(...nodes);
    }
};
BbFocusTrap.ctorParameters = () => [
    { type: Platform },
    { type: ElementRef }
];
__decorate([
    HostListener('keydown', ['$event'])
], BbFocusTrap.prototype, "onKeydown", null);
BbFocusTrap = __decorate([
    Directive({
        selector: '[bbFocusTrap]'
    })
], BbFocusTrap);

class BbButtonBase {
    constructor(_elementRef) {
        this._elementRef = _elementRef;
    }
}
const BbButtonMixinBase = mixinDisabled(mixinLoad(BbButtonBase));
let BbButton = class BbButton extends BbButtonMixinBase {
    constructor(_elementRef) {
        super(_elementRef);
    }
    get nativeElement() {
        return this._elementRef.nativeElement;
    }
    focus() {
        this.nativeElement && this.nativeElement.focus();
    }
};
BbButton.ctorParameters = () => [
    { type: ElementRef }
];
BbButton = __decorate([
    Component({
        selector: 'button[bb-button]',
        template: "<bb-spinner [class.visible]=\"loading\"\n            class=\"bb-button-spinner small\">\n</bb-spinner>\n\n<ng-content></ng-content>\n",
        exportAs: 'bbButton',
        host: {
            'class': 'bb-button',
            '[class.loading]': 'loading',
            '[attr.disabled]': 'disabled || loading || null'
        },
        inputs: ['disabled', 'loading'],
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        styles: [".bb-button{height:38px;padding:0 8px;cursor:pointer;font-size:16px;font-weight:500;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;font-style:normal;border-radius:4px;text-align:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;text-decoration:none;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;background-color:#fff;color:#2d3c4d!important;border:1px solid #d4d8e1;-webkit-transition-duration:.2s;transition-duration:.2s;box-shadow:0 6px 6px -6px rgba(0,0,0,.1);-webkit-transition-timing-function:cubic-bezier(0,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);-webkit-transition-property:padding-left,background-color,box-shadow;transition-property:padding-left,background-color,box-shadow}.bb-button:hover{background-color:#fcfcfb}.bb-button:active,.bb-button:focus{box-shadow:0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(220,224,233,.5)}.bb-button.full{width:100%}.bb-button.full.loading{padding-left:42px}.bb-button.primary{border-color:#2f2b85;color:#fff!important;background-color:#5b53ff}.bb-button.primary:hover{background-color:#564ee6}.bb-button.primary:active,.bb-button.primary:focus{box-shadow:0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(91,83,255,.5)}.bb-button.destructive{border-color:#8f2020;color:#fff!important;background-color:#d32f2f}.bb-button.destructive:hover{background-color:#c32929}.bb-button.destructive:active,.bb-button.destructive:focus{box-shadow:0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(211,47,47,.5)}.bb-button.loading,.bb-button.loading:active,.bb-button.loading:focus,.bb-button.loading:hover,.bb-button:disabled,.bb-button:disabled:active,.bb-button:disabled:focus,.bb-button:disabled:hover,.bb-button[disabled],.bb-button[disabled]:active,.bb-button[disabled]:focus,.bb-button[disabled]:hover{opacity:.4;cursor:default;box-shadow:none}.bb-button-spinner{width:0;opacity:0;overflow:hidden;visibility:hidden;padding:0!important;-webkit-transition:width .2s cubic-bezier(0,0,.2,1),opacity .1s cubic-bezier(0,0,.2,1);transition:width .2s cubic-bezier(0,0,.2,1),opacity .1s cubic-bezier(0,0,.2,1)}.bb-button-spinner.visible{opacity:1;width:20px;margin-right:8px;visibility:visible}.bb-button.loading.full>.bb-button-spinner{left:8px;margin-right:0;position:absolute}"]
    })
], BbButton);
let BbAnchor = class BbAnchor extends BbButton {
    constructor(_elementRef) {
        super(_elementRef);
    }
    stopDisabledEvents(event) {
        // If the button is not disabled (and not loading) let all events pass.
        if (!this.disabled && !this.loading) {
            return;
        }
        // If the button is disabled and/or loading stop
        // the event from bubbling up.
        event.preventDefault();
        event.stopImmediatePropagation();
    }
};
BbAnchor.ctorParameters = () => [
    { type: ElementRef }
];
__decorate([
    Input()
], BbAnchor.prototype, "tabIndex", void 0);
BbAnchor = __decorate([
    Component({
        selector: 'a[bb-button]',
        template: "<bb-spinner [class.visible]=\"loading\"\n            class=\"bb-button-spinner small\">\n</bb-spinner>\n\n<ng-content></ng-content>\n",
        exportAs: 'bbButton, bbAnchor',
        host: {
            'class': 'bb-button',
            '[attr.tabindex]': '(disabled || loading) ? -1 : (tabIndex || 0)',
            '[attr.disabled]': 'disabled || loading || null',
            '[attr.aria-disabled]': '(disabled || loading).toString()',
            '(click)': 'stopDisabledEvents($event)'
        },
        inputs: ['disabled', 'loading'],
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        styles: [".bb-button{height:38px;padding:0 8px;cursor:pointer;font-size:16px;font-weight:500;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;font-style:normal;border-radius:4px;text-align:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;text-decoration:none;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;background-color:#fff;color:#2d3c4d!important;border:1px solid #d4d8e1;-webkit-transition-duration:.2s;transition-duration:.2s;box-shadow:0 6px 6px -6px rgba(0,0,0,.1);-webkit-transition-timing-function:cubic-bezier(0,0,.2,1);transition-timing-function:cubic-bezier(0,0,.2,1);-webkit-transition-property:padding-left,background-color,box-shadow;transition-property:padding-left,background-color,box-shadow}.bb-button:hover{background-color:#fcfcfb}.bb-button:active,.bb-button:focus{box-shadow:0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(220,224,233,.5)}.bb-button.full{width:100%}.bb-button.full.loading{padding-left:42px}.bb-button.primary{border-color:#2f2b85;color:#fff!important;background-color:#5b53ff}.bb-button.primary:hover{background-color:#564ee6}.bb-button.primary:active,.bb-button.primary:focus{box-shadow:0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(91,83,255,.5)}.bb-button.destructive{border-color:#8f2020;color:#fff!important;background-color:#d32f2f}.bb-button.destructive:hover{background-color:#c32929}.bb-button.destructive:active,.bb-button.destructive:focus{box-shadow:0 6px 6px -6px rgba(0,0,0,.1),0 0 0 3px rgba(211,47,47,.5)}.bb-button.loading,.bb-button.loading:active,.bb-button.loading:focus,.bb-button.loading:hover,.bb-button:disabled,.bb-button:disabled:active,.bb-button:disabled:focus,.bb-button:disabled:hover,.bb-button[disabled],.bb-button[disabled]:active,.bb-button[disabled]:focus,.bb-button[disabled]:hover{opacity:.4;cursor:default;box-shadow:none}.bb-button-spinner{width:0;opacity:0;overflow:hidden;visibility:hidden;padding:0!important;-webkit-transition:width .2s cubic-bezier(0,0,.2,1),opacity .1s cubic-bezier(0,0,.2,1);transition:width .2s cubic-bezier(0,0,.2,1),opacity .1s cubic-bezier(0,0,.2,1)}.bb-button-spinner.visible{opacity:1;width:20px;margin-right:8px;visibility:visible}.bb-button.loading.full>.bb-button-spinner{left:8px;margin-right:0;position:absolute}"]
    })
], BbAnchor);

let BbTemplate = class BbTemplate {
    constructor(_templateRef, _viewContainerRef) {
        this._templateRef = _templateRef;
        this._viewContainerRef = _viewContainerRef;
    }
    set bbTemplate(content) {
        // Get the template.
        const template = content instanceof TemplateRef
            ? content
            : this._templateRef;
        // Clear the view container ref and create the view.
        this._viewContainerRef.clear();
        this._viewContainerRef.createEmbeddedView(template);
    }
};
BbTemplate.ctorParameters = () => [
    { type: TemplateRef },
    { type: ViewContainerRef }
];
__decorate([
    Input()
], BbTemplate.prototype, "bbTemplate", null);
BbTemplate = __decorate([
    Directive({
        selector: '[bbTemplate]'
    })
], BbTemplate);

let BbAutosize = class BbAutosize {
    constructor(_renderer, _elementRef) {
        this._renderer = _renderer;
        this._elementRef = _elementRef;
        // Min/max heights for the textarea.
        this.minHeight = null;
        this.maxHeight = null;
    }
    get element() {
        return this._elementRef.nativeElement;
    }
    ngAfterViewInit() {
        // Update the styles after the DOM has loaded.
        this.updateStyles();
    }
    onWindowResize() {
        // Update the styles when the window is resized.
        this.updateStyles();
    }
    onInputReceived() {
        // Update the styles after the textarea received input.
        this.updateStyles();
    }
    updateStyles() {
        // If the element does not exist exit.
        if (!this.element) {
            return;
        }
        // If the scroll height is the same height as the element, then exit.
        if (this.element.style.height === this.element.scrollHeight + 'px') {
            return;
        }
        // Set the style of the element to 'auto' to reset the element.
        this._renderer.setStyle(this.element, 'height', 'auto');
        // Set the style of the element to the scroll height to make
        // the element fit all the text.
        this._renderer.setStyle(this.element, 'height', this.element.scrollHeight + 'px');
    }
};
BbAutosize.ctorParameters = () => [
    { type: Renderer2 },
    { type: ElementRef }
];
__decorate([
    Input(), HostBinding('style.min-height')
], BbAutosize.prototype, "minHeight", void 0);
__decorate([
    Input(), HostBinding('style.max-height')
], BbAutosize.prototype, "maxHeight", void 0);
__decorate([
    HostListener('window:resize')
], BbAutosize.prototype, "onWindowResize", null);
__decorate([
    HostListener('input')
], BbAutosize.prototype, "onInputReceived", null);
BbAutosize = __decorate([
    Directive({
        selector: 'textarea[bbAutosize]'
    })
], BbAutosize);

var BbCheckbox_1;
let nextUniqueId$2 = 0;
class BbCheckboxBase {
}
const BbCheckboxMixinBase = mixinDisabled(mixinGrouped(BbCheckboxBase));
let BbCheckbox = BbCheckbox_1 = class BbCheckbox extends BbCheckboxMixinBase {
    constructor(_changeDetection) {
        super();
        this._changeDetection = _changeDetection;
        // Data.
        this.labelId = `bb-checkbox-${nextUniqueId$2++}`;
        this._checked = false;
        // Methods.
        this.onChange = () => {
        };
        this.onTouched = () => {
        };
    }
    get checked() {
        return this._checked;
    }
    set checked(value) {
        this._checked = coerceBooleanProperty(value);
        this._changeDetection.markForCheck();
    }
    registerOnChange(fn) {
        this.onChange = fn;
    }
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    setDisabledState(isDisabled) {
        this.disabled = isDisabled;
        this._changeDetection.markForCheck();
    }
    writeValue(newValue) {
        this.checked = newValue;
    }
    onInteractionEvent(event) {
        // Stop the propagation to prevent it from bubbling up.
        event.stopPropagation();
    }
    onInputClick(event) {
        // Stop the propagation to prevent it from bubbling up.
        event.stopPropagation();
        // Toggle the value.
        this.checked = !this.checked;
        // Emit the change event.
        this.onChange && this.onChange(this.checked);
    }
};
BbCheckbox.ctorParameters = () => [
    { type: ChangeDetectorRef }
];
__decorate([
    Input()
], BbCheckbox.prototype, "tabIndex", void 0);
__decorate([
    Input()
], BbCheckbox.prototype, "checked", null);
BbCheckbox = BbCheckbox_1 = __decorate([
    Component({
        selector: 'bb-checkbox',
        template: "<input [id]=\"labelId\"\n       [checked]=\"checked\"\n       [disabled]=\"disabled\"\n       (change)=\"onInteractionEvent($event)\"\n       (click)=\"onInputClick($event)\"\n       class=\"bb-checkbox-input\"\n       tabindex=\"-1\"\n       type=\"checkbox\">\n\n<label [for]=\"labelId\"\n       [attr.tabindex]=\"disabled ? -1 : (tabIndex || 0)\"\n       (keyup.space)=\"onInputClick($event)\"\n       class=\"bb-checkbox-label\">\n    <span>\n        <svg width=\"12px\"\n             height=\"10px\"\n             viewbox=\"0 0 12 10\">\n            <polyline points=\"1.5 6 4.5 9 10.5 1\"></polyline>\n        </svg>\n    </span>\n    <span>\n        <ng-content></ng-content>\n    </span>\n</label>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        providers: [
            { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => BbCheckbox_1), multi: true }
        ],
        host: {
            'class': 'bb-checkbox',
            '[class.grouped]': 'grouped'
        },
        inputs: ['grouped', 'disabled'],
        preserveWhitespaces: false,
        styles: [".bb-checkbox{display:block}.bb-checkbox+.bb-checkbox{margin-top:5px}.bb-checkbox.grouped{margin-bottom:20px}.bb-checkbox-input{display:none}.bb-checkbox-label{margin:0;display:-webkit-box;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bb-checkbox-label>span{display:inline-block;vertical-align:middle;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bb-checkbox-label>span:first-child{width:18px;height:18px;min-width:18px;min-height:18px;position:relative;border-radius:3px;vertical-align:middle;border:1px solid #bdc4c9;-webkit-transition:.2s;transition:.2s}.bb-checkbox-label>span:last-child{padding-left:8px}.bb-checkbox-label>span:first-child>svg{top:3px;left:2px;fill:none;stroke:#fff;stroke-width:2;position:absolute;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:16px;stroke-dashoffset:16px;-webkit-transition:.3s;transition:.3s;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bb-checkbox-input:not(:disabled):not(:checked)+.bb-checkbox-label:focus>span:first-child{box-shadow:0 0 0 3px rgba(222,205,205,.5)}.bb-checkbox-input:not(:disabled):checked+.bb-checkbox-label:focus>span:first-child{box-shadow:0 0 0 3px rgba(91,83,255,.5)}.bb-checkbox-input:checked+.bb-checkbox-label>span:first-child{border-color:#5b53ff;background-color:#5b53ff}.bb-checkbox-input:checked+.bb-checkbox-label>span:first-child>svg{stroke-dashoffset:0}.bb-checkbox-input:disabled+.bb-checkbox-label{cursor:default;pointer-events:none}.bb-checkbox-input:disabled:checked+.bb-checkbox-label>span:first-child{border-color:rgba(204,204,204,.64);background-color:rgba(204,204,204,.64)}"]
    })
], BbCheckbox);

class BbSpinnerBase {
}
const BbSpinnerMixinBase = mixinDisabled(BbSpinnerBase);
let BbSpinner = class BbSpinner extends BbSpinnerMixinBase {
    constructor() {
        super(...arguments);
        // Inputs.
        this.color = '#303f9f';
        this.alt = 'Loading...';
    }
};
__decorate([
    Input()
], BbSpinner.prototype, "color", void 0);
__decorate([
    Input()
], BbSpinner.prototype, "alt", void 0);
BbSpinner = __decorate([
    Component({
        selector: 'bb-spinner',
        template: "<!--\n    The spinner element.\n\n    This element contains a circle with a 25% bar that spins\n    indefinitely. The border color can be set via the \"color\"\n    property.\n-->\n<div class=\"bb-spinner-container\">\n    <div [style.border-left-color]=\"color\"\n         [class.disabled]=\"disabled\"\n         class=\"bb-spinner-loader\"\n         aria-live=\"assertive\"\n         role=\"alert\">\n        {{ alt }}\n    </div>\n    <ng-content select=\"img\"></ng-content>\n</div>\n\n<!--\n    The content of the spinner.\n\n    This element contains the content of the spinner. The user\n    can set the content inside the tag.\n-->\n<span class=\"bb-spinner-content\">\n    <ng-content></ng-content>\n</span>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: { 'class': 'bb-spinner' },
        inputs: ['color', 'alt', 'disabled'],
        preserveWhitespaces: false,
        styles: [".bb-spinner{color:#565656;padding:20px 0;text-align:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.bb-spinner.block{display:-webkit-box;display:-ms-flexbox;display:flex}.bb-spinner.inverse .bb-spinner-loader{border-color:rgba(255,255,255,.15)}.bb-spinner.inverse .bb-spinner-content{color:rgba(255,255,255,.5)}.bb-spinner.small .bb-spinner-loader,.bb-spinner.small .bb-spinner-loader:after{width:20px;height:20px;min-width:20px;min-height:20px}.bb-spinner.small .bb-spinner-loader{border-width:2px}.bb-spinner.small .bb-spinner-content{font-size:12px}.bb-spinner.medium .bb-spinner-loader,.bb-spinner.medium .bb-spinner-loader:after{width:60px;height:60px;min-width:60px;min-height:60px}.bb-spinner.medium .bb-spinner-loader{border-width:4px}.bb-spinner.medium .bb-spinner-content{font-size:16px}.bb-spinner.large .bb-spinner-loader,.bb-spinner.large .bb-spinner-loader:after{width:100px;height:100px;min-width:100px;min-height:100px}.bb-spinner.large .bb-spinner-loader{border-width:6px}.bb-spinner.large .bb-spinner-content{font-size:20px}.bb-spinner.horizontal{text-align:left;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.bb-spinner.horizontal .bb-spinner-content:not(:empty){margin-left:10px;margin-top:0}.bb-spinner.vertical{text-align:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.bb-spinner.vertical .bb-spinner-content:not(:empty){margin-left:0;margin-top:10px}.bb-spinner-container{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative}.bb-spinner-container>img{top:20%;left:20%;width:60%;height:60%;position:absolute}.bb-spinner-loader{margin:0;padding:0;overflow:hidden;text-indent:100%;color:transparent;position:relative;display:inline-block;vertical-align:middle;border:4px solid #f2f4f6;-webkit-animation:1s linear infinite spin;animation:1s linear infinite spin}.bb-spinner-loader,.bb-spinner-loader:after{width:60px;height:60px;min-width:60px;min-height:60px;border-radius:50%}.bb-spinner-loader.disabled{cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-animation-play-state:paused;animation-play-state:paused}.bb-spinner-content:not(:empty){font-size:16px;margin-top:10px;font-weight:500}@-webkit-keyframes spin{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spin{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}"]
    })
], BbSpinner);

let BbFocus = class BbFocus {
    constructor(_zone, _platform, _elementRef) {
        this._zone = _zone;
        this._platform = _platform;
        this._elementRef = _elementRef;
    }
    get nativeElement() {
        return this._elementRef.nativeElement;
    }
    ngAfterViewInit() {
        // Run the method outside the Angular zone.
        this._zone.runOutsideAngular(() => this.focus());
    }
    focus() {
        // Check if set timeout exists and the user is
        // using the site on desktop devices.
        if (!this._platform.isDesktop || !setTimeout) {
            return;
        }
        // Check if the element and the focus method exist, if so focus the element.
        if (!this.nativeElement || !this.nativeElement.focus) {
            return;
        }
        // Execute the focus method in a timeout.
        setTimeout(() => this.nativeElement.focus(), 0);
    }
};
BbFocus.ctorParameters = () => [
    { type: NgZone },
    { type: Platform },
    { type: ElementRef }
];
BbFocus = __decorate([
    Directive({
        selector: '[bbFocus]'
    })
], BbFocus);

let BbFileImage = class BbFileImage {
    constructor(_image, _sanitizer) {
        this._image = _image;
        this._sanitizer = _sanitizer;
    }
    transform(file) {
        return __awaiter(this, void 0, void 0, function* () {
            // If the file is not a file return.
            if (!(file instanceof File)) {
                return null;
            }
            return this._image.fileToImage(file, [
                'image/png',
                'image/jpeg',
                'image/gif',
                'image/svg+xml'
            ]).then(image => {
                if (!image) {
                    return null;
                }
                return {
                    background: this._sanitizer.bypassSecurityTrustStyle(`url(${image.src})`),
                    aspectRatio: image.height / image.width
                };
            }).catch(() => {
                return null;
            });
        });
    }
};
BbFileImage.ctorParameters = () => [
    { type: ImageConverter },
    { type: DomSanitizer }
];
BbFileImage = __decorate([
    Pipe({
        name: 'bbFileImage'
    })
], BbFileImage);

let BbAvatar = class BbAvatar {
    constructor() {
        // Inputs.
        this.size = 40;
        // State.
        this.state$ = new BehaviorSubject('initials');
        // Data.
        this._src = null;
        this._title = null;
        this._initials = '!';
        this._color = 'rgb(255, 255, 255)';
        this._backgroundColor = 'rgb(66, 66, 66)';
        this.toRGb = (value) => {
            const baseRed = 128;
            const baseGreen = 128;
            const baseBlue = 128;
            let seed = value.charCodeAt(0) ^ value.charCodeAt(1);
            const rand_1 = Math.abs((Math.sin(seed++) * 10000)) % 256;
            const rand_2 = Math.abs((Math.sin(seed++) * 10000)) % 256;
            const rand_3 = Math.abs((Math.sin(seed++) * 10000)) % 256;
            const r = Math.round((rand_1 + baseRed) / 2);
            const g = Math.round((rand_2 + baseGreen) / 2);
            const b = Math.round((rand_3 + baseBlue) / 2);
            return { r, g, b };
        };
        this.getInitials = (name) => {
            // Get all the initials.
            const names = (name || '').split(' ');
            const initials = names.map(name => name.charAt(0).toUpperCase());
            // Check if there are any initials.
            if (initials.length <= 0) {
                return null;
            }
            // Get the first and last initials.
            if (initials.length > 1) {
                return `${initials[0]}${initials[initials.length - 1]}`;
            }
            // Get only the first initial.
            return initials[0];
        };
        this.parseColorFormat = (value) => {
            // Hex 3 values.
            let match = value.match(/^#([0-9a-f]{3})$/i);
            if (match && match[1]) {
                const r = parseInt(match[1].charAt(0), 16) * 0x11;
                const g = parseInt(match[1].charAt(1), 16) * 0x11;
                const b = parseInt(match[1].charAt(2), 16) * 0x11;
                return { r, g, b };
            }
            // Hex 6 values.
            match = value.match(/^#([0-9a-f]{6})$/i);
            if (match && match[1]) {
                const r = parseInt(match[1].substr(0, 2), 16);
                const g = parseInt(match[1].substr(2, 2), 16);
                const b = parseInt(match[1].substr(4, 2), 16);
                return { r, g, b };
            }
            // Rgb values.
            match = value.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
            if (match) {
                const r = parseInt(match[1], 10);
                const g = parseInt(match[2], 10);
                const b = parseInt(match[3], 10);
                return { r, g, b };
            }
            // Not a supported color format.
            this.logWarning(`BbAvatar: Unsupported tintColor "${value}" was used.`);
            return null;
        };
        this.logWarning = (message) => {
            console && console.warn && console.warn(message);
        };
    }
    set src(value) {
        this._src = value;
        if (this._src) {
            this.state$.next('image');
        }
    }
    set title(value) {
        // Set the title and the initials.
        this._title = value || '!';
        this._initials = this.getInitials(this._title);
        // Generate the colors based on the name.
        const { r, g, b } = this.toRGb(this._title);
        this.setColors(r, g, b);
    }
    set tintColor(value) {
        const result = this.parseColorFormat(value);
        if (!result) {
            return;
        }
        const { r, g, b } = result;
        this.setColors(r, g, b);
    }
    get src() {
        return this._src;
    }
    get color() {
        return this._color;
    }
    get backgroundColor() {
        return this._backgroundColor;
    }
    get title() {
        return this._title;
    }
    get initials() {
        return this._initials;
    }
    setColors(red, green, blue) {
        this._color = `rgb(${red},${green},${blue})`;
        this._backgroundColor = `rgba(${red},${green},${blue}, 0.25)`;
    }
};
__decorate([
    Input()
], BbAvatar.prototype, "size", void 0);
__decorate([
    Input()
], BbAvatar.prototype, "src", null);
__decorate([
    Input(),
    HostBinding('attr.title')
], BbAvatar.prototype, "title", null);
__decorate([
    Input()
], BbAvatar.prototype, "tintColor", null);
BbAvatar = __decorate([
    Component({
        selector: 'bb-avatar',
        template: "<ng-container [ngSwitch]=\"state$ | async\">\n    <!-- Image. -->\n    <ng-container *ngSwitchCase=\"'image'\">\n        <img [src]=\"src\"\n             [alt]=\"initials\"\n             (error)=\"state$?.next('initials')\"\n             class=\"bb-avatar-image\">\n    </ng-container>\n\n    <!-- Default initials fallback. -->\n    <ng-container *ngSwitchDefault>\n        {{ initials }}\n    </ng-container>\n</ng-container>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        preserveWhitespaces: false,
        host: {
            'class': 'bb-avatar',
            'role': 'img',
            '[style.width.px]': 'size',
            '[style.height.px]': 'size',
            '[style.font-size.px]': 'size / 2',
            '[style.color]': 'color',
            '[style.background-color]': 'backgroundColor'
        },
        styles: [".bb-avatar{line-height:1;font-size:18px;overflow:hidden;font-weight:500;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;border-radius:50%;-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.bb-avatar.rounded{border-radius:4px}.bb-avatar.square{border-radius:0}.bb-avatar-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;position:absolute}"]
    })
], BbAvatar);

let BbFileSize = class BbFileSize {
    constructor() {
        this.format = (value, decimals = 2) => {
            if (value === 0) {
                return '0 Bytes';
            }
            const k = 1024;
            const dm = decimals < 0 ? 0 : decimals;
            const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
            const index = Math.floor(Math.log(value) / Math.log(k));
            return parseFloat((value / Math.pow(k, index)).toFixed(dm)) + ' ' + sizes[index];
        };
    }
    transform(value) {
        return this.format(value);
    }
};
BbFileSize = __decorate([
    Pipe({
        name: 'bbFileSize'
    })
], BbFileSize);

let BbIcon = class BbIcon {
    constructor(_registry) {
        this._registry = _registry;
        // Data.
        this._src = null;
        // State.
        this.state$ = new BehaviorSubject(null);
        this.alt = null;
        this.size = 24;
        this._ariaHidden = true;
        this.warn = (content) => {
            return console && console.warn && console.warn(content);
        };
    }
    set src(newValue) {
        this.state$.next(this.convert(newValue));
        this._src = newValue;
    }
    get src() {
        return this._src;
    }
    set ariaHidden(newValue) {
        this._ariaHidden = coerceBooleanProperty(newValue);
    }
    get ariaHidden() {
        return this._ariaHidden;
    }
    convert(src) {
        const [namespace, value] = (src || '').split(':');
        const onError = () => {
            this.warn(`ElementsModule: The icon with src "${src}" could not be rendered correctly; Did you put a correct src attribute?`);
            return { type: 'unknown' };
        };
        if (!namespace || !value || !this._registry) {
            return onError();
        }
        // Try to find a image icon.
        const imageIcon = this.findImageIcon(namespace, value);
        if (imageIcon) {
            return imageIcon;
        }
        // Try to find a font icon.
        const fontIcon = this.findFontIcon(namespace, value);
        if (fontIcon) {
            return fontIcon;
        }
        // Return the on error function.
        return onError();
    }
    findImageIcon(namespace, value) {
        const data = this._registry.find(item => item['namespace'] === namespace && item['name'] === value);
        if (!data) {
            return null;
        }
        return { type: data['type'], src: data['src'] };
    }
    findFontIcon(namespace, content) {
        const data = this._registry.find(item => item['namespace'] === namespace);
        if (!data) {
            return null;
        }
        const isInline = data['inline'] || false;
        if (isInline) {
            return { type: data['type'], className: `${data['className']}${content}` };
        }
        return { type: data['type'], className: data['className'], content };
    }
};
BbIcon.ctorParameters = () => [
    { type: Array, decorators: [{ type: Optional }, { type: Inject, args: [ELEMENTS_ICONS,] }] }
];
__decorate([
    Input()
], BbIcon.prototype, "alt", void 0);
__decorate([
    Input()
], BbIcon.prototype, "size", void 0);
__decorate([
    Input()
], BbIcon.prototype, "src", null);
__decorate([
    Input()
], BbIcon.prototype, "ariaHidden", null);
BbIcon = __decorate([
    Component({
        selector: 'bb-icon',
        template: "<ng-container *ngIf=\"state$ | async as data\"\n              [ngSwitch]=\"data?.type\">\n    <i *ngSwitchCase=\"'font'\"\n       [class]=\"data?.className\">\n        {{ data?.content }}\n    </i>\n    <img *ngSwitchCase=\"'image'\"\n         [src]=\"data?.src\"\n         [alt]=\"alt\">\n    <svg *ngSwitchCase=\"'unknown'\"\n         viewBox=\"0 0 1 1\">\n        <rect x=\"0\" y=\"0\" width=\"1\" height=\"1\" fill=\"#c5c5c5\"></rect>\n    </svg>\n</ng-container>\n",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        host: {
            'class': 'bb-icon',
            '[attr.aria-hidden]': 'ariaHidden',
            '[style.width.px]': 'size',
            '[style.height.px]': 'size',
            '[style.min-width.px]': 'size',
            '[style.min-height.px]': 'size'
        },
        preserveWhitespaces: false,
        styles: [".bb-icon{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.bb-icon>img,.bb-icon>svg{width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex}"]
    }),
    __param(0, Optional()), __param(0, Inject(ELEMENTS_ICONS))
], BbIcon);

let BbTag = class BbTag {
    constructor() {
        // Outputs.
        this.onClose = new EventEmitter();
    }
};
__decorate([
    Output()
], BbTag.prototype, "onClose", void 0);
BbTag = __decorate([
    Component({
        selector: 'bb-tag',
        template: "<ng-content></ng-content>\n\n<button *ngIf=\"onClose?.observers?.length > 0\"\n        (click)=\"onClose.emit()\"\n        type=\"button\">\n    Close\n</button>",
        changeDetection: ChangeDetectionStrategy.OnPush,
        encapsulation: ViewEncapsulation.None,
        preserveWhitespaces: false,
        host: { 'class': 'bb-tag' },
        styles: [".bb-tag{cursor:default;padding:0 7px;font-size:12px;list-style:none;line-height:20px;border-radius:4px;white-space:nowrap;display:inline-block;color:rgba(0,0,0,.65);border:1px solid #d9d9d9;background-color:#fafafa;font-variant:tabular-nums;font-feature-settings:\"tnum\"}.bb-tag:not(:last-child){margin-right:8px}"]
    })
], BbTag);

var ElementsModule_1;
const DECLARATIONS_EXPORTS = [
    // Directives.
    BbTemplate,
    BbFormError,
    BbFormSubmit,
    BbInput,
    BbSelect,
    BbFocus,
    BbFocusTrap,
    BbAutosize,
    BbPrefix,
    BbSuffix,
    // Pipes.
    BbFileSize,
    BbFileImage,
    // Components.
    BbButton,
    BbAnchor,
    BbSpinner,
    BbIcon,
    BbFormControl,
    BbFormGroup,
    BbCheckbox,
    BbImagePicker,
    BbDropdown,
    BbDropdownItem,
    BbTag,
    BbAvatar,
    BbFilePicker
];
let ElementsModule = ElementsModule_1 = class ElementsModule {
    static forRoot() {
        return {
            ngModule: ElementsModule_1,
            providers: [
                { provide: ELEMENTS_ERRORS, useFactory: getErrors, multi: true },
                ELEMENTS_MATERIAL_ICON
            ]
        };
    }
};
ElementsModule = ElementsModule_1 = __decorate([
    NgModule({
        imports: [CommonModule, LocalizeModule],
        declarations: [...DECLARATIONS_EXPORTS],
        exports: [...DECLARATIONS_EXPORTS]
    })
], ElementsModule);
const ɵ0 = { namespace: 'material', className: 'material-icons', type: 'font' };
const ELEMENTS_MATERIAL_ICON = {
    provide: ELEMENTS_ICONS,
    useValue: ɵ0,
    multi: true
};
function getErrors() {
    const data = {
        unknown: () => 'form-control-errors.unknown',
        required: () => 'form-control-errors.required',
        pattern: () => 'form-control-errors.pattern',
        email: () => 'form-control-errors.email',
        emailTaken: () => 'form-control-errors.emailTaken',
        passwordMatch: () => 'form-control-errors.passwordMatch',
        fullNumber: () => 'form-control-errors.fullNumber',
        min: ({ min }) => ({ token: 'form-control-errors.min', data: { min } }),
        max: ({ max }) => ({ token: 'form-control-errors.max', data: { max } }),
        maxFileSize: ({ maxSize }) => ({ token: 'form-control-errors.maxFileSize', data: { maxSize } }),
        minlength: ({ requiredLength, actualLength }) => ({
            token: 'form-control-errors.minlength',
            data: { requiredLength, actualLength }
        }),
        maxlength: ({ requiredLength, actualLength }) => ({
            token: 'form-control-errors.maxlength',
            data: { requiredLength, actualLength }
        })
    };
    return data;
}

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

export { BbAnchor, BbAutosize, BbAvatar, BbButton, BbCheckbox, BbDropdown, BbDropdownItem, BbFileImage, BbFilePicker, BbFileSize, BbFocus, BbFocusTrap, BbFormControl, BbFormError, BbFormGroup, BbFormSubmit, BbIcon, BbImagePicker, BbInput, BbPrefix, BbSelect, BbSpinner, BbSuffix, BbTag, BbTemplate, ELEMENTS_ERRORS, ELEMENTS_ICONS, ELEMENTS_MATERIAL_ICON, ElementsModule, getErrors, ɵ0 };
//# sourceMappingURL=bravobit-bb-foundation-elements.js.map
