UNPKG

@c10t/nice-component-library

Version:

nice-component-library

9,446 lines 522 kB
import * as i1$2 from '@angular/forms';
import { FormGroup, FormArray, FormControl, Validators, NgControl, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i1$3 from '@angular/common/http';
import { HttpParams, HttpHeaders, HttpResponse, HttpResponseBase } from '@angular/common/http';
import * as i0 from '@angular/core';
import { InjectionToken, Self, Optional, Inject, Component, Injectable, Directive, EventEmitter, Output, Input, Host, Pipe, HostListener, forwardRef, ViewChild, HostBinding, ViewEncapsulation, NgModule, NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import * as i1$1 from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import * as i1 from '@ngx-translate/core';
import { TranslateModule } from '@ngx-translate/core';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i3 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i6 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i4 from '@angular/material/input';
import { MAT_INPUT_VALUE_ACCESSOR, MatInputModule } from '@angular/material/input';
import * as i8 from '@angular/flex-layout/flex';
import * as i3$1 from 'ngx-toastr';
import { BehaviorSubject, Subject, of, forkJoin, debounceTime, distinctUntilChanged, filter, tap, switchMap, throwError } from 'rxjs';
import * as i5 from '@angular/material/table';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import * as i1$4 from '@angular/router';
import { RouterModule } from '@angular/router';
import * as i2$1 from 'ngx-filesaver';
import { catchError, map, finalize } from 'rxjs/operators';
import * as i1$5 from '@angular/material/paginator';
import { MatPaginatorIntl, MatPaginatorModule } from '@angular/material/paginator';
import * as i4$1 from '@angular/material/checkbox';
import { MatCheckboxModule } from '@angular/material/checkbox';
import * as i7 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i8$1 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import * as i9 from '@angular/flex-layout/extended';
import * as i7$1 from '@angular/material/menu';
import { MatMenuModule } from '@angular/material/menu';
import * as i2$2 from '@angular/platform-browser';
import * as i5$1 from '@angular/cdk/text-field';
import * as i4$2 from '@angular/material/core';
import { NativeDateAdapter, DateAdapter, MAT_DATE_FORMATS, MatRippleModule, MatCommonModule } from '@angular/material/core';
import * as i5$2 from '@angular/material/datepicker';
import { MatDatepickerModule } from '@angular/material/datepicker';
import * as i10 from '@angular/cdk/scrolling';
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
import * as i9$1 from '@angular/material/select';
import { MatSelectModule } from '@angular/material/select';
import * as i3$2 from '@angular/material/autocomplete';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import * as i9$2 from '@angular/material/progress-spinner';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import * as i3$3 from '@angular/material/card';
import { MatCardModule } from '@angular/material/card';
import * as i3$4 from '@angular/material/progress-bar';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { NestedTreeControl, FlatTreeControl, CdkTreeModule, CdkTree, CdkTreeNode } from '@angular/cdk/tree';
import * as i6$1 from '@angular/material/tree';
import { MatTreeNestedDataSource, MatTreeFlattener, MatTreeFlatDataSource, MatTreeModule } from '@angular/material/tree';
import * as i4$3 from '@angular/material/radio';
import { MatRadioModule } from '@angular/material/radio';
import * as i6$2 from '@angular/material/divider';
import * as i4$4 from 'ngx-quill';
import { QuillModule } from 'ngx-quill';
import * as i1$6 from 'jsog-typescript';
import { OverlayModule } from '@angular/cdk/overlay';
import { A11yModule } from '@angular/cdk/a11y';
import { BidiModule } from '@angular/cdk/bidi';
import { ObserversModule } from '@angular/cdk/observers';
import { PortalModule } from '@angular/cdk/portal';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatSliderModule } from '@angular/material/slider';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatListModule } from '@angular/material/list';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatChipsModule } from '@angular/material/chips';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatSortModule } from '@angular/material/sort';
import { MatStepperModule } from '@angular/material/stepper';
import { ScrollingModule as ScrollingModule$1 } from '@angular/cdk-experimental/scrolling';
import { FlexLayoutModule } from '@angular/flex-layout';

class NavigatorModel {
    displayName = '';
    disabled = true;
    iconName = '';
    roleMenu = '';
    route = '';
    children = [];
    isOnlyIcon = true;
    expanded = false;
}

class ButtonClickEvent {
    action;
    object;
    index;
    constructor(action, object, index) {
        this.action = action;
        this.object = object;
        this.index = index;
    }
}

var IconTypeEnum;
(function (IconTypeEnum) {
    IconTypeEnum["MATERIAL_ICON"] = "MATERIAL_ICON";
    IconTypeEnum["FONT_AWESOME"] = "FONT_AWESOME";
})(IconTypeEnum || (IconTypeEnum = {}));

class ButtonModel {
    columnDef = '';
    color = 'warn';
    icon = '';
    iconType = IconTypeEnum.MATERIAL_ICON;
    click = '';
    isShowHeader;
    title = '';
    display;
    disabled;
    className;
    header;
    alignHeader;
}

class CheckboxModel {
    id;
    viewValue;
    checked;
    disabled;
    constructor(id, viewValue, checked, disabled) {
        this.id = id;
        this.viewValue = viewValue;
        this.checked = checked;
        this.disabled = disabled;
    }
}

var ColumnTypeEnum;
(function (ColumnTypeEnum) {
    ColumnTypeEnum["VIEW"] = "VIEW";
    ColumnTypeEnum["INPUT_COUNTER"] = "INPUT_COUNTER";
    ColumnTypeEnum["DATE_PICKER"] = "DATE_PICKER";
    ColumnTypeEnum["MULTI_SELECT_AUTOCOMPLETE"] = "MULTI_SELECT_AUTOCOMPLETE";
    ColumnTypeEnum["CHECKBOX"] = "CHECKBOX";
    ColumnTypeEnum["BASE64"] = "BASE64";
    ColumnTypeEnum["IMG"] = "IMG";
    ColumnTypeEnum["IMG_NO_SECURE"] = "IMG_NO_SECURE";
    // HTML = 'HTML',
    // INNER_TEXT = 'INNER_TEXT',
    ColumnTypeEnum["BUTTON"] = "BUTTON";
    ColumnTypeEnum["INPUT"] = "INPUT";
    ColumnTypeEnum["LINK"] = "LINK";
    ColumnTypeEnum["STYLE_CSS"] = "STYLE_CSS";
    ColumnTypeEnum["LIVE_SEARCHING"] = "LIVE_SEARCHING";
})(ColumnTypeEnum || (ColumnTypeEnum = {}));

var AlignEnum;
(function (AlignEnum) {
    AlignEnum["LEFT"] = "start";
    AlignEnum["CENTER"] = "center";
    AlignEnum["RIGHT"] = "end";
})(AlignEnum || (AlignEnum = {}));

class ColumnModel {
    columnDef = '';
    header;
    // set default theo ly thuyet, phai gan lai
    align = AlignEnum.LEFT;
    alignHeader;
    // phục vụ cho loại cột là hiển thị đường dẫn
    link;
    // Phục vụ cho style css
    style;
    className;
    headerClassName;
    columnType = ColumnTypeEnum.VIEW;
    onCellValueChange;
    onHeaderCellValueChange;
    disabled;
    optionValues;
    display;
    isShowHeader = false;
    isNotShowHeaderCheckbox = false;
    isRequired = false;
    min;
    max;
    hasWordBreakStyle = false;
    validate;
    errorMessage;
    isTree = false;
    isMultipleSelect = false;
    isDecimal = false;
    isExpandOptionColumn;
    footer;
    footers = [];
    button;
    // Dùng cho cva-live-searching
    displayKey;
    mappingConfig = {};
    searchFn;
    title = (e) => `${e}`;
    cell = (e) => `${e}`;
}

class BaseModel {
    id;
    checked = false;
    invalid = false;
    createdDate;
    createdBy;
    lastModifiedDate;
    lastModifiedBy;
}

class MenuModel extends BaseModel {
    clientId = null;
    code = null;
    url = null;
    appType = null;
    parentMenu = null;
    constructor(form) {
        super();
        if (form instanceof FormGroup) {
            this.id = form.get('id')?.value;
            this.clientId = form.get('clientId')?.value;
            this.code = form.get('code')?.value;
            this.url = form.get('url')?.value;
            this.appType = form.get('appType')?.value;
            if (form.get('parentMenu')?.value) {
                this.parentMenu = new MenuModel(form.get('parentMenu')?.value);
            }
        }
        else {
            this.id = form;
        }
    }
}

class OAuth2AuthenticationDto {
    userAuthentication = null;
    authorities = null;
    name = null;
    orgId = null;
    orgCode = null;
    orgName = null;
    orgType = null;
    orgForm = null;
    orgPath = null;
    orgIsApproveVo = null;
    sapId = null;
    voAuthentication = null;
}

class Authority {
    authority = '';
}

class TablePagingResponseModel {
    content = [];
    page = {
        size: null,
        number: null,
        totalElements: null,
        totalPages: null,
    };
}

class TablePagingRequestModel {
    text = '';
    pageSize = 0;
    pageNumber = 0;
    totalElements = 0;
}

class RoleModel extends BaseModel {
    clientId = null;
    roleName = null;
    description = '';
    permissions = [];
    menus = [];
    constructor(form) {
        super();
        if (!form) {
            return;
        }
        if (form instanceof FormGroup) {
            const formId = form.get('id');
            if (formId) {
                this.id = formId.value;
            }
            const formClientId = form.get('clientId');
            if (formClientId) {
                this.clientId = formClientId.value;
            }
            const formRoleName = form.get('roleName');
            if (formRoleName) {
                this.roleName = formRoleName.value;
            }
            const formDescription = form.get('description');
            if (formDescription) {
                this.description = formDescription.value;
            }
        }
        else {
            this.id = form;
        }
    }
}

class SelectModel {
    value;
    displayValue;
    disabled;
    rawData;
    constructor(value, displayValue, disabled, rawData) {
        this.value = value;
        this.displayValue = displayValue;
        this.disabled = disabled;
        this.rawData = rawData;
    }
}

class UIState {
    moduleName = '';
    formGroup = new FormGroup({});
}

var FileTypeEnum;
(function (FileTypeEnum) {
    FileTypeEnum["DOCX"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
    FileTypeEnum["JPG"] = "image/jpeg";
    FileTypeEnum["PDF"] = "application/pdf";
    FileTypeEnum["PNG"] = "image/png";
    FileTypeEnum["RTF"] = "application/msword";
    FileTypeEnum["TXT"] = "text/plain";
    FileTypeEnum["XLSX"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    FileTypeEnum["XML"] = "text/xml";
    FileTypeEnum["ZIP"] = "application/x-zip-compressed";
    FileTypeEnum["DOC"] = "application/msword";
    FileTypeEnum["XLS"] = "application/vnd.ms-excel";
})(FileTypeEnum || (FileTypeEnum = {}));

class UploadModel {
    id;
    name;
    type;
    binary;
    previewValue;
    constructor(name, binary, previewValue, type, id) {
        this.name = name;
        this.binary = binary;
        this.previewValue = previewValue;
        this.type = type;
        this.id = id;
    }
    static init(url) {
        const type = UploadModel.getFileType(url);
        const name = UploadModel.getFileName(url);
        return new UploadModel(name ? name : '', null, url, type);
    }
    static getFileType(url) {
        const fileTypes = url ? url.split('.') : [];
        const type = fileTypes.length > 0 ? fileTypes[fileTypes.length - 1] : '';
        if (['png', 'jpg', 'jpeg', 'img'].includes(type?.toLowerCase())) {
            return 'image/' + type;
        }
        else if ('pdf' === type?.toLowerCase()) {
            return 'application/pdf';
        }
        return type;
    }
    static getFileName(url) {
        let fileName = url ? url.split('/') : [];
        return fileName.pop();
    }
}

class BreadCrumbModel {
    label;
    url;
    constructor(label, url) {
        this.label = label;
        this.url = url;
    }
}

class FlatTreeModel {
    rootData = [];
    value = (node) => `${node}`;
    display = (node) => `${node}`;
    children = (node) => [];
}

class TableFooterModel {
    columnDef = '';
    title = (e) => `${e}`;
    cell = (e) => `${e}`;
    colspan = 1;
    align = AlignEnum.LEFT;
    className;
    display; // default is false
}

class RangeDatePickerModel {
    fromDate = '';
    toDate = '';
    constructor(fromDate, toDate) {
        this.fromDate = fromDate ? fromDate : '';
        this.toDate = toDate ? toDate : '';
    }
    isString(inputValue) {
        return typeof inputValue === 'string' || inputValue instanceof String;
    }
    reset() {
        this.toDate = '';
        this.fromDate = '';
    }
}

class FlatTreeConfigModel {
    isDynamicConfig = false; /* bằng true khi muốn call liên tục hàm display và hàm disabled */
    display = true;
    disabled = false;
}

class FlatTreeNodeModel {
    children = [];
    value;
    displayValue = '';
    checked;
    checkedDisplay;
    filterChecked;
    level = 0;
    expandable;
    isExpanded; // storage expanded status in selected tree
    isFilterExpanded; // storage expanded status in choose tree
    display = true;
    _displayFuncInput;
    disabled = false;
    _disabledFuncInput;
}

var DialogTypeEnum;
(function (DialogTypeEnum) {
    DialogTypeEnum["CONFIRM"] = "CONFIRM";
    DialogTypeEnum["ERROR"] = "ERROR";
    DialogTypeEnum["INPUT_CONFIRM"] = "INPUT_CONFIRM";
})(DialogTypeEnum || (DialogTypeEnum = {}));

class CustomDialogDataConfigModel {
    type = DialogTypeEnum.CONFIRM;
    maxLength;
    msg;
    msgDetail;
    errorMsg;
    btnOKString;
    btnOKClass;
    btnOK_IconClass;
    btnCancelClass;
    btnCancel_IconClass;
    btnCancelString;
    customClass;
    hideIconButton;
}

class Principal {
    username = null;
    firstName = null;
    middleName = null;
    lastName = null;
    fullName = null;
    gender = null;
    email = null;
    phone = null;
    voAuthentication = null;
    orgId = null;
    orgCode = null;
    orgName = null;
    orgType = null;
    orgForm = null;
    orgSapId = null;
    orgPath = null;
    orgIsApproveVo = null;
    roles = [];
    mustChangePassword = null;
}

class DialogImportFileConfigModel {
    downloadTemplateFunc;
    importFunc;
    downloadErrorFile;
    confirmMsgKey = '';
    successMsgKey = '';
    errorMsgKey = '';
}

class PermissionModel extends BaseModel {
    clientId;
    description;
    id = null;
    url;
}

var ActionTypeEnum;
(function (ActionTypeEnum) {
    ActionTypeEnum["_ADD"] = "add";
    ActionTypeEnum["_EDIT"] = "edit";
    ActionTypeEnum["_VIEW"] = "view";
})(ActionTypeEnum || (ActionTypeEnum = {}));

var BaseStatusEnum;
(function (BaseStatusEnum) {
    BaseStatusEnum["_"] = "base.status.all";
    BaseStatusEnum["_DRAFT"] = "base.status.draft";
    BaseStatusEnum["_APPROVED"] = "base.status.approved";
    BaseStatusEnum["_REJECTED"] = "base.status.rejected";
})(BaseStatusEnum || (BaseStatusEnum = {}));

class BaseTableComponent {
    activatedRoute;
    authoritiesService;
    me = null;
    constructor(activatedRoute, authoritiesService) {
        this.activatedRoute = activatedRoute;
        this.authoritiesService = authoritiesService;
        if (!this.authoritiesService.me && this.activatedRoute.snapshot.data) {
            this.me = this.activatedRoute.snapshot.data['me'];
        }
        if (!!this.authoritiesService.me) {
            this.me = this.authoritiesService.me;
        }
        if (!!this.me) {
            this.authoritiesService.me = this.me;
            this.authoritiesService.stateMe.next(this.me);
        }
    }
    onRowButtonClick(event) {
        const window = this;
        if (window[event.action]) {
            window[event.action](event.object, event.index);
        }
    }
    _collectParams(searchForm, map) {
        let params = new HttpParams();
        for (const key of Object.keys(map)) {
            const value = map[key];
            if (value) {
                const control = searchForm.get(value);
                if (control) {
                    params = params.set(key, control.value ? control.value : '');
                }
            }
        }
        return params;
    }
}

const InjectTokenNextSolutionsConfig = new InjectionToken('InjectTokenNextSolutionsConfig');

class CvaCustomDialogComponent {
    translateService;
    dialogRef;
    injector;
    data;
    config;
    get DialogTypeEnum() {
        return DialogTypeEnum;
    }
    inputText = '';
    errorInputText = '';
    isError = false;
    constructor(translateService, dialogRef, injector, ngControl, data) {
        this.translateService = translateService;
        this.dialogRef = dialogRef;
        this.injector = injector;
        this.data = data;
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
        this.config = injector.get(InjectTokenNextSolutionsConfig);
    }
    writeValue(obj) {
        this.inputText = obj;
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched(fn) {
    }
    ngOnInit() {
    }
    onConfirm() {
        if (this.data && this.data.type) {
            if (this.data.type === DialogTypeEnum.INPUT_CONFIRM) {
                this.isError = !this.inputText.trim();
                if (this.isError) {
                    this.errorInputText = !!this.data?.errorMsg ? this.translateService.instant(this.data.errorMsg) : this.translateService.instant('common.required');
                    return;
                }
                this.dialogRef.close({ value: this.inputText });
            }
            else {
                this.dialogRef.close({ value: 1 });
            }
        }
    }
    onCancel() {
        this.dialogRef.close();
    }
    onChangeInput() {
        this.isError = !this.inputText.trim();
        if (this.isError) {
            this.errorInputText = !!this.data?.errorMsg ? this.translateService.instant(this.data.errorMsg) : this.translateService.instant('common.required');
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaCustomDialogComponent, deps: [{ token: i1.TranslateService }, { token: i1$1.MatDialogRef }, { token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaCustomDialogComponent, isStandalone: false, selector: "cva-custom-dialog", ngImport: i0, template: `
    <div class="cva-custom-dialog dialog-content {{data.customClass}}" *ngIf="data"

         style="padding-bottom: 0px !important;"
         fxLayout="column">
      <div class="img"
           fxLayoutAlign="center center"
           fxLayout
           *ngIf="config && config.DIALOG_LOGO">
        <img src="{{config.DIALOG_LOGO}}" alt="confirm-logo" />
      </div>
      <div class="content"
           fxLayoutAlign="start stretch"
           fxLayout="column">
        <div class="text-msg">
          {{ data && data.msg ? data.msg : '' }}
        </div>
        <div class="text-msg-detail" *ngIf="data && data.msgDetail">
          {{ data.msgDetail }}
        </div>
        <!--                <div class="text-error" *ngIf="data.type === DialogTypeEnum.ERROR">-->
        <!--                    {{data && data.msg ? data.msg : ''}}-->
        <!--                </div>-->
        <!--                <div class="text-area" *ngIf="data.type === DialogTypeEnum.INPUT_CONFIRM"-->
        <!--                     fxLayoutAlign="center center"-->
        <!--                     fxLayout="column">-->
        <!--                    <label fxLayoutAlign="center center"-->
        <!--                           fxLayout>{{data && data.msg ? data.msg : ''}}</label>-->

        <mat-form-field appearance="outline" class="input-confirm-dialog" fxFlex="100%"
                        fxLayout="column" *ngIf="data.type === DialogTypeEnum.INPUT_CONFIRM">
                            <textarea matInput [(ngModel)]="inputText" fxFlex="100%"
                                      maxlength="{{(data && !!data.maxLength) ? data.maxLength : 524288}}"
                                      (ngModelChange)="onChangeInput()"></textarea>
          <span *ngIf="!!data && !!data.maxLength" class="input-suffix"
                matSuffix>{{ (inputText?.length ? inputText.length : 0) + '/' + data.maxLength }}</span>
          <mat-hint style="color: red" *ngIf="isError">{{ errorInputText }}</mat-hint>
        </mat-form-field>
        <!--                </div>-->
      </div>
    </div>
    <hr class="display-hr-tag" *ngIf="data.type !== DialogTypeEnum.INPUT_CONFIRM">
    <div class="buttonArea margin-top-10">
      <button mat-button
              class="{{data.btnCancelClass ? data.btnCancelClass : 'primary outline'}} btn-Cancel"
              *ngIf="data.type !== DialogTypeEnum.ERROR"
              (click)="onCancel()">
        <i *ngIf="!data.hideIconButton"
           class="{{data.btnCancel_IconClass ? data.btnCancel_IconClass : 'fa fa-times' }}"></i> {{ data && data.btnCancelString ? data.btnCancelString : ('common.Cancel' | translate) }}
      </button>
      <button mat-button
              class="{{data.btnOKClass ? data.btnOKClass : 'primary'}} btn-OK"
              (click)="onConfirm()">
        <i *ngIf="!data.hideIconButton"
           class="{{data.btnOK_IconClass ? data.btnOK_IconClass : 'fa fa-check'}}"></i> {{ data && data.btnOKString ? data.btnOKString : ('common.OK' | translate) }}
      </button>
    </div>

  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaCustomDialogComponent, decorators: [{
            type: Component,
            args: [{ selector: 'cva-custom-dialog', standalone: false, template: `
    <div class="cva-custom-dialog dialog-content {{data.customClass}}" *ngIf="data"

         style="padding-bottom: 0px !important;"
         fxLayout="column">
      <div class="img"
           fxLayoutAlign="center center"
           fxLayout
           *ngIf="config && config.DIALOG_LOGO">
        <img src="{{config.DIALOG_LOGO}}" alt="confirm-logo" />
      </div>
      <div class="content"
           fxLayoutAlign="start stretch"
           fxLayout="column">
        <div class="text-msg">
          {{ data && data.msg ? data.msg : '' }}
        </div>
        <div class="text-msg-detail" *ngIf="data && data.msgDetail">
          {{ data.msgDetail }}
        </div>
        <!--                <div class="text-error" *ngIf="data.type === DialogTypeEnum.ERROR">-->
        <!--                    {{data && data.msg ? data.msg : ''}}-->
        <!--                </div>-->
        <!--                <div class="text-area" *ngIf="data.type === DialogTypeEnum.INPUT_CONFIRM"-->
        <!--                     fxLayoutAlign="center center"-->
        <!--                     fxLayout="column">-->
        <!--                    <label fxLayoutAlign="center center"-->
        <!--                           fxLayout>{{data && data.msg ? data.msg : ''}}</label>-->

        <mat-form-field appearance="outline" class="input-confirm-dialog" fxFlex="100%"
                        fxLayout="column" *ngIf="data.type === DialogTypeEnum.INPUT_CONFIRM">
                            <textarea matInput [(ngModel)]="inputText" fxFlex="100%"
                                      maxlength="{{(data && !!data.maxLength) ? data.maxLength : 524288}}"
                                      (ngModelChange)="onChangeInput()"></textarea>
          <span *ngIf="!!data && !!data.maxLength" class="input-suffix"
                matSuffix>{{ (inputText?.length ? inputText.length : 0) + '/' + data.maxLength }}</span>
          <mat-hint style="color: red" *ngIf="isError">{{ errorInputText }}</mat-hint>
        </mat-form-field>
        <!--                </div>-->
      </div>
    </div>
    <hr class="display-hr-tag" *ngIf="data.type !== DialogTypeEnum.INPUT_CONFIRM">
    <div class="buttonArea margin-top-10">
      <button mat-button
              class="{{data.btnCancelClass ? data.btnCancelClass : 'primary outline'}} btn-Cancel"
              *ngIf="data.type !== DialogTypeEnum.ERROR"
              (click)="onCancel()">
        <i *ngIf="!data.hideIconButton"
           class="{{data.btnCancel_IconClass ? data.btnCancel_IconClass : 'fa fa-times' }}"></i> {{ data && data.btnCancelString ? data.btnCancelString : ('common.Cancel' | translate) }}
      </button>
      <button mat-button
              class="{{data.btnOKClass ? data.btnOKClass : 'primary'}} btn-OK"
              (click)="onConfirm()">
        <i *ngIf="!data.hideIconButton"
           class="{{data.btnOK_IconClass ? data.btnOK_IconClass : 'fa fa-check'}}"></i> {{ data && data.btnOKString ? data.btnOKString : ('common.OK' | translate) }}
      </button>
    </div>

  ` }]
        }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i1$1.MatDialogRef }, { type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }, { type: CustomDialogDataConfigModel, decorators: [{
                    type: Inject,
                    args: [MAT_DIALOG_DATA]
                }] }] });

class UtilsService {
    dialog;
    transService;
    toastr;
    constructor(dialog, transService, toastr) {
        this.dialog = dialog;
        this.transService = transService;
        this.toastr = toastr;
    }
    static getEnumValue(o, value) {
        return o['_' + value]; // No type safety here unfrotunately
    }
    static calcPosition(e, results, paging) {
        return (paging ? ((paging.pageNumber - 1) * paging.pageSize) : 0) + (results.data.indexOf(e) + 1);
    }
    static reduceEntityAttributeForFormControl(formGroup, e, dateRangeConfigList) {
        return Object.keys(formGroup.controls).reduce(reduceEntityAttributeForFormControlByControlName, {});
        function reduceEntityAttributeForFormControlByControlName(formControl, ctrlName) {
            if (e) {
                let includesOfDateRangeConfig = false;
                if (dateRangeConfigList) {
                    for (const dateRangeConfig of dateRangeConfigList) {
                        if (dateRangeConfig
                            && [dateRangeConfig.dateRangeControlName,
                                dateRangeConfig.fromDateControlName, dateRangeConfig.toDateControlName].includes(ctrlName)) {
                            includesOfDateRangeConfig = true;
                            switch (ctrlName) {
                                case dateRangeConfig.dateRangeControlName:
                                    formControl[ctrlName] = {
                                        fromDate: e[dateRangeConfig.fromDateControlName] ? e[dateRangeConfig.fromDateControlName] : null,
                                        toDate: e[dateRangeConfig.toDateControlName] ? e[dateRangeConfig.toDateControlName] : null,
                                    };
                                    break;
                                case dateRangeConfig.fromDateControlName:
                                    formControl[ctrlName] = e[ctrlName];
                                    if (formControl[dateRangeConfig.dateRangeControlName]
                                        && typeof (formControl[dateRangeConfig.dateRangeControlName]) === 'object') {
                                        formControl[dateRangeConfig.dateRangeControlName].fromDate = e[ctrlName];
                                    }
                                    break;
                                case dateRangeConfig.toDateControlName:
                                    formControl[ctrlName] = e[ctrlName];
                                    if (formControl[dateRangeConfig.dateRangeControlName]
                                        && typeof (formControl[dateRangeConfig.dateRangeControlName]) === 'object') {
                                        formControl[dateRangeConfig.dateRangeControlName].toDate = e[ctrlName];
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
                if (!includesOfDateRangeConfig) {
                    if (typeof (e[ctrlName]) === 'boolean') {
                        formControl[ctrlName] = e[ctrlName] ? '1' : '0';
                    }
                    else if (e[ctrlName] instanceof Array) {
                        formControl[ctrlName] = e[ctrlName];
                    }
                    else if (typeof (e[ctrlName]) === 'object') {
                        formControl[ctrlName] = e[ctrlName]
                            ? (e[ctrlName].id
                                ? e[ctrlName].id
                                : (e[ctrlName].code ? e[ctrlName].code : ''))
                            : null;
                    }
                    else {
                        formControl[ctrlName] = (e[ctrlName] != null && e[ctrlName] != undefined) ? e[ctrlName] : '';
                    }
                }
            }
            else {
                formControl[ctrlName] = '';
            }
            return formControl;
        }
    }
    static cloneAbstractControl(control) {
        let newControl;
        if (control instanceof FormGroup) {
            const formGroup = new FormGroup({}, control.validator, control.asyncValidator);
            const controls = control.controls;
            if (controls) {
                Object.keys(controls).forEach(key => {
                    const tempControl = UtilsService.cloneAbstractControl(controls[key]);
                    if (tempControl) {
                        formGroup.addControl(key, tempControl);
                    }
                });
            }
            newControl = formGroup;
        }
        else if (control instanceof FormArray) {
            const formArray = new FormArray([], control.validator, control.asyncValidator);
            const controls = control.controls;
            if (controls) {
                controls.forEach((formControl) => {
                    const tempControl = UtilsService.cloneAbstractControl(formControl);
                    if (tempControl) {
                        formArray.push(tempControl);
                    }
                });
            }
            newControl = formArray;
        }
        else if (control instanceof FormControl || this.isNgControl(control)) {
            newControl = new FormControl(control.value, control.validator, control.asyncValidator);
        }
        else {
            console.error('Error: unexpected formControl value', control);
        }
        if (control.disabled && newControl)
            newControl.disable({ emitEvent: false });
        return newControl;
    }
    static isNgControl(control) {
        return control && 'control' in control;
    }
    static convertTreeDataToAutocompleteData(treeFields, symbol, hasChildFn, nodes, prefixDisplayValue) {
        let result = [];
        if (treeFields) {
            for (const node of nodes) {
                const value = treeFields.value(node).toString();
                const displayValue = prefixDisplayValue ? prefixDisplayValue + symbol + treeFields.display(node) : treeFields.display(node);
                const hasChild = hasChildFn(0, node);
                if (hasChild) {
                    const childen = treeFields.children(node);
                    result.push(...this.convertTreeDataToAutocompleteData(treeFields, symbol, hasChildFn, childen, displayValue));
                }
                else {
                    result.push(new SelectModel(value, displayValue, hasChild, node));
                }
            }
        }
        return result;
    }
    strFormat(str, replacement) {
        let a = this.transService.instant(str);
        if (replacement === null || replacement === undefined || replacement.length === 0) {
            return a;
        }
        replacement.forEach((value, index) => {
            a = a.replace('{' + index + '}', this.transService.instant(value));
        });
        return a;
    }
    onSuccessFunc = (onSuccessMessage) => {
        if (onSuccessMessage) {
            const msg = this.transService.instant(onSuccessMessage);
            this.toastr.toastrConfig.positionClass = 'toast-bottom-right';
            this.toastr.success(msg);
        }
    };
    showWarningToarst(msgKey, replacement) {
        const msg = this.strFormat(msgKey, replacement);
        this.toastr.toastrConfig.positionClass = 'toast-bottom-right';
        this.toastr.warning(msg);
    }
    showErrorToarst(msgKey, replacement) {
        const msg = this.strFormat(msgKey, replacement);
        this.toastr.toastrConfig.positionClass = 'toast-bottom-right';
        this.toastr.error(msg);
    }
    showError = (err) => {
        let errLocale = '';
        if (err !== undefined && err !== null) {
            errLocale = this.transService.instant(err);
        }
        this.dialog.open(CvaCustomDialogComponent, {
            width: '500px',
            data: {
                msg: `${errLocale}`,
                type: DialogTypeEnum.ERROR,
            },
        });
    };
    execute3(apiCall, onSuccessFunc, onSuccessMessage, onErrorFunc) {
        if (!apiCall) {
            if (onSuccessFunc) {
                onSuccessFunc(null);
            }
            return;
        }
        apiCall.subscribe((data) => {
            if (onSuccessFunc) {
                if (onSuccessMessage) {
                    onSuccessFunc(data, onSuccessMessage);
                }
                else {
                    onSuccessFunc(data);
                }
            }
            else {
                this.onSuccessFunc(onSuccessMessage);
            }
        }, (error1) => {
            if (error1 !== '401') {
                if (!!onErrorFunc) {
                    onErrorFunc(error1);
                }
                else {
                    this.showError(error1);
                }
            }
        });
    }
    execute(apiCall, onSuccessFunc, onSuccessMessage, confirmMsgTitle, confirmMsgTitleParamsFormat = [], confirmMsgDetail = '', confirmMsgDetailParamsFormat = [], confirmDialogConfig = undefined, confirmDialogButtonOk = 'common.OK', confirmDialogButtonCancel = 'common.Cancel') {
        if (confirmMsgTitle !== undefined && confirmMsgTitle !== null && confirmMsgTitle !== '') {
            this.showConfirmDialog(confirmMsgTitle, confirmMsgTitleParamsFormat, confirmMsgDetail, confirmMsgDetailParamsFormat, confirmDialogConfig, confirmDialogButtonOk, confirmDialogButtonCancel)
                .afterClosed().subscribe(result => {
                if (result && result.value) {
                    this.execute3(apiCall, onSuccessFunc, onSuccessMessage);
                }
            });
        }
        else {
            this.execute3(apiCall, onSuccessFunc, onSuccessMessage);
        }
    }
    executeWithErrorHandle(method, onSuccessFunc, onSuccessMessage, confirmMsgTitle, confirmMsgParamsFormat = [], confirmMsgDetail = '', confirmMsgDetailParamsFormat = [], onErrorFunc, dialogConfig, confirmDialogButtonOk = 'common.OK', confirmDialogButtonCancel = 'common.Cancel') {
        if (confirmMsgTitle !== undefined && confirmMsgTitle !== null && confirmMsgTitle !== '') {
            this.showConfirmDialog(confirmMsgTitle, confirmMsgParamsFormat, confirmMsgDetail, confirmMsgDetailParamsFormat, dialogConfig, confirmDialogButtonOk, confirmDialogButtonCancel)
                .afterClosed().subscribe((result) => {
                if (result && result.value) {
                    this.execute3(method(), onSuccessFunc, onSuccessMessage, onErrorFunc);
                }
            });
        }
        else {
            this.execute3(method(), onSuccessFunc, onSuccessMessage, onErrorFunc);
        }
    }
    showConfirmDialog(strTitle, replacementTitle, strDetailMsg = '', replacementDetail = [], confirmDialogConfig = undefined, strOkText = 'common.OK', strCancelTex = 'common.Cancel', strCustomClass) {
        const msgTitle = this.strFormat(strTitle, replacementTitle);
        const msgDetail = !!strDetailMsg ? this.strFormat(strDetailMsg, replacementDetail) : '';
        const strOk = this.transService.instant(strOkText);
        const strCancel = this.transService.instant(strCancelTex);
        const re = /\./gi;
        const customClass = (strCustomClass ? strCustomClass : strTitle).replace(re, '-');
        return this.dialog.open(CvaCustomDialogComponent, confirmDialogConfig ? confirmDialogConfig : {
            width: '500px',
            data: {
                customClass: customClass,
                msg: msgTitle,
                msgDetail: msgDetail,
                type: DialogTypeEnum.CONFIRM,
                btnOKString: strOk,
                btnCanceString: strCancel,
            },
        });
    }
    showConfirmInputDialog(str1, replacement, confirmInputDialogConfig = undefined, strOkText = 'common.OK', strCancelTex = 'common.Cancel', strCustomClass) {
        const str = this.strFormat(str1, replacement);
        const strOk = this.transService.instant(strOkText);
        const strCancel = this.transService.instant(strCancelTex);
        const re = /\./gi;
        const customClass = (strCustomClass ? strCustomClass : str1).replace(re, '-');
        return this.dialog.open(CvaCustomDialogComponent, confirmInputDialogConfig ? confirmInputDialogConfig : {
            width: '500px',
            data: {
                customClass: customClass,
                msg: str,
                type: DialogTypeEnum.INPUT_CONFIRM,
                btnOKString: strOk,
                btnCancelString: strCancel,
            },
        });
    }
    getEnumValueTranslated(o, value) {
        const key = o['_' + value]; // No type safety here unfrotunately
        return this.transService.instant(key);
    }
    toBlobJon(obj) {
        return new Blob([JSON.stringify(obj)], {
            type: 'application/json',
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UtilsService, deps: [{ token: i1$1.MatDialog }, { token: i1.TranslateService }, { token: i3$1.ToastrService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UtilsService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UtilsService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i1$1.MatDialog }, { type: i1.TranslateService }, { type: i3$1.ToastrService }] });

class ApiService {
    http;
    fileSaver;
    injector;
    config;
    constructor(http, fileSaver, injector) {
        this.http = http;
        this.fileSaver = fileSaver;
        this.injector = injector;
        this.config = injector.get(InjectTokenNextSolutionsConfig);
    }
    getFullUrl(url) {
        return this.config.BASE_URL + url;
    }
    get(nativeUrl, params, baseUrl) {
        return this.http.get(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), { params });
    }
    getJSON(file) {
        return this.http.get(file);
    }
    getBlob(nativeUrl, params, baseUrl) {
        const url = baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl);
        return this.http.get(url, {
            responseType: 'blob', // Đặt responseType thành 'blob'
        });
    }
    post(nativeUrl, obj, options, baseUrl) {
        return this.http.post(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), obj, options ? {
            headers: options.headers,
            params: options.params,
        } : {});
    }
    postBlob(nativeUrl, obj, options, baseUrl) {
        return this.http.post(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), obj, {
            headers: options.headers,
            params: options.params,
            observe: 'response',
            responseType: 'blob',
        });
    }
    patch(nativeUrl, obj, options, baseUrl) {
        return this.http.patch(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), obj, options ? { headers: options.headers, params: options.params } : {});
    }
    put(nativeUrl, obj, options, baseUrl) {
        return this.http.put(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), obj, options ? { headers: options.headers, params: options.params } : {});
    }
    delete(nativeUrl, options, baseUrl) {
        return this.http.delete(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), options ? {
            headers: options.headers,
            params: options.params,
        } : {});
    }
    saveFile(nativeUrl, obj, options, baseUrl, onErrorFunc) {
        this.http.post(baseUrl ? (baseUrl + nativeUrl) : this.getFullUrl(nativeUrl), obj, {
            headers: options.headers,
            params: options.params,
            observe: 'response',
            responseType: 'blob',
        }).subscribe((l) => {
            let filename = '';
            const disposition = l.headers.get('Content-Disposition');
            if (disposition && disposition.indexOf('attachment') !== -1) {
                const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                const matches = filenameRegex.exec(disposition);
                if (matches != null && matches[1]) {
                    filename = matches[1].replace(/['"]/g, '');
                }
            }
            const blobData = l.body;
            const contentType = l.headers.get('Content-Type');
            if (blobData && contentType) {
                this.fileSaver.save(blobData, filename, contentType);
            }
        }, (err) => {
            if (onErrorFunc) {
                onErrorFunc(err);
            }
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ApiService, deps: [{ token: i1$3.HttpClient }, { token: i2$1.FileSaverService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ApiService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ApiService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i1$3.HttpClient }, { type: i2$1.FileSaverService }, { type: i0.Injector }] });

class FormStateService {
    subject = new BehaviorSubject(new Map());
    uiState$ = this.subject.asObservable();
    setMapState(mapState) {
        this.subject.next(mapState);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: FormStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: FormStateService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: FormStateService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

class AuthoritiesService {
    me = null;
    stateMe = new BehaviorSubject(new OAuth2AuthenticationDto());
    me$ = this.stateMe.asObservable();
    hasAuthorities(authorities) {
        if (!authorities) {
            return false;
        }
        let checkAuthority = false;
        for (const authority of authorities) {
            checkAuthority = checkAuthority || this.hasAuthority(authority.toLowerCase());
            if (checkAuthority) {
                break;
            }
        }
        return checkAuthority;
    }
    hasAuthority(authority) {
        if (!authority || !this.me || !this.me.authorities) {
            return false;
        }
        return this.me.authorities.map(x => x.authority.toString().toLowerCase()).includes(authority.toLowerCase());
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AuthoritiesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AuthoritiesService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AuthoritiesService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

class BaseSearchComponent extends BaseTableComponent {
    router;
    apiService;
    utilsService;
    formStateService;
    translateService;
    injector;
    activatedRoute;
    authoritiesService;
    formGroup;
    isAdvancedSearch = false;
    searchForm;
    paging;
    results = new MatTableDataSource([]);
    columns = [];
    config;
    moduleName = '';
    unsubscribe$ = new Subject();
    isResetPaging = true;
    constructor(router, apiService, utilsService, formStateService, translateService, injector, activatedRoute, authoritiesService, formGroup) {
        super(activatedRoute, authoritiesService);
        this.router = router;
        this.apiService = apiService;
        this.utilsService = utilsService;
        this.formStateService = formStateService;
        this.translateService = translateService;
        this.injector = injector;
        this.activatedRoute = activatedRoute;
        this.authoritiesService = authoritiesService;
        this.formGroup = formGroup;
        this.searchForm = this.formGroup;
        this.config = injector.get(InjectTokenNextSolutionsConfig);
        this.paging = new TablePagingRequestModel();
        this.paging.pageSize = this.config.PAGE_SIZE;
        this.paging.pageNumber = 1;
        this.paging.totalElements = 0;
    }
    ngOnInit() {
        this.formStateService.uiState$
            .subscribe((mapState) => {
            if (mapState && mapState.has(this.moduleName)) {
                const stateFormGroup = mapState.get(this.moduleName);
                if (stateFormGroup) {
                    const formGroup = UtilsService.cloneAbstractControl(stateFormGroup);
                    if (formGroup) {
                        if (!this.searchForm) {
                            this.searchForm = formGroup;
                        }
                        else {
                            const formControls = formGroup.controls;
                            Object.keys(formControls).forEach(key => {
                                const abstractControl = this.searchForm.get(key);
                                if (abstractControl) {
                                    abstractControl.setValue(formControls[key].value);
                                }
                            });
                        }
                    }
                }
            }
        });
    }
    ngAfterViewInit() {
        Object.keys(this.searchForm.controls).forEach(key => {
            const abstractControl = this.searchForm.get(key);
            if (abstractControl) {
                abstractControl.valueChanges.subscribe(value => {
                    this.isResetPaging = true;
                });
            }
        });
    }
    ngOnDestroy() {
        let isOK = false;
        this.formStateService.uiState$.subscribe((mapState) => {
            if (!isOK) {
                isOK = true;
                mapState.set(this.moduleName, this.searchForm);
                this.formStateService.setMapState(mapState);
                this.unsubscribe$.next();
                this.unsubscribe$.complete();
            }
        });
    }
    onSubmit() {
        this.isResetPaging = true;
        this.search();
    }
    search() {
        // Form extends will be override custom by business
    }
    afterSearch = (data) => {
        // Form extends will be override custom by business
    };
    _fillData(nativeUrl, params, baseUrl) {
        params = this.updateHttpParams(params);
        this.apiService.get(nativeUrl, params, baseUrl).subscribe(this.afterFillData);
    }
    _fillDataByPostMethod(nativeUrl, obj, options, baseUrl) {
        options.params = this.updateHttpParams(options.params);
        this.apiService.post(nativeUrl, obj, options, baseUrl).subscribe(this.afterFillData);
    }
    pagingChange(event) {
        if (this.paging) {
            this.paging = event;
            this.search();
        }
        else {
            this.paging = event;
        }
    }
    onClick(event) {
        // Form extends will be override custom by business
    }
    onSuccessFunc = (data, onSuccessMessage) => {
        this.utilsService.onSuccessFunc(onSuccessMessage ? onSuccessMessage : 'common.default.success');
        this.search();
    };
    resetSearchFormValue() {
        if (!this.searchForm) {
            return;
        }
        for (const ctrName in this.searchForm.controls) {
            this.searchForm.controls[ctrName].setValue('');
        }
    }
    toggleAdvancedSearch() {
        this.isAdvancedSearch = !this.isAdvancedSearch;
    }
    params2Object(params) {
        const result = {};
        params = this.removeEmptyParams(params);
        params.keys().forEach(k => {
            const value = params.get(k);
            if (value && value.indexOf(',') >= 0) {
                result[k] = value?.split(',');
            }
            else {
                result[k] = value;
            }
        });
        return result;
    }
    afterFillData = (data) => {
        this.isResetPaging = false;
        if (data.content && data.content.length > 0) {
            this.columns.forEach((column) => {
                column.isShowHeader = false;
            });
        }
        this.afterSearch(data);
        this.results = new MatTableDataSource(data.content);
        this.paging = new TablePagingRequestModel();
        this.paging.pageSize = data.page.size ? data.page.size : 0;
        this.paging.pageNumber = (data.page.number ? data.page.number : 0) + 1;
        this.paging.totalElements = data.page.totalElements ? data.page.totalElements : 0;
    };
    removeEmptyParams(params) {
        params.keys().forEach(key => {
            const value = params.get(key) ? params.get(key) + '' : '';
            if (value) {
                params = params.set(key, value.trim());
            }
        });
        const emptyValuesKey = params.keys().filter(key => !params.get(key));
        emptyValuesKey.forEach(key => {
            params = params.delete(key);
        });
        return params;
    }
    updateHttpParams(params) {
        params = this.removeEmptyParams(params);
        if (!params.keys().includes('pageNumber')) {
            params = params.append('pageNumber', this.isResetPaging ? '1' : (this.paging ? this.paging.pageNumber.toString() : '1'))
                .append('pageSize', this.paging ? this.paging.pageSize.toString() : this.config.PAGE_SIZE.toString());
        }
        return params;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BaseSearchComponent, deps: [{ token: i1$4.Router }, { token: ApiService }, { token: UtilsService }, { token: FormStateService }, { token: i1.TranslateService }, { token: i0.Injector }, { token: i1$4.ActivatedRoute }, { token: AuthoritiesService }, { token: i1$2.FormGroup }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: BaseSearchComponent, isStandalone: false, selector: "BaseSearchComponent", usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BaseSearchComponent, decorators: [{
            type: Directive,
            args: [{
                    selector: 'BaseSearchComponent',
                    standalone: false,
                }]
        }], ctorParameters: () => [{ type: i1$4.Router }, { type: ApiService }, { type: UtilsService }, { type: FormStateService }, { type: i1.TranslateService }, { type: i0.Injector }, { type: i1$4.ActivatedRoute }, { type: AuthoritiesService }, { type: i1$2.FormGroup }] });

class BaseAddEditComponent extends BaseTableComponent {
    activatedRoute;
    location;
    translateService;
    utilsService;
    authoritiesService;
    addEditForm = new FormGroup({});
    isEdit;
    id;
    isView = false;
    constructor(activatedRoute, location, translateService, utilsService, authoritiesService) {
        super(activatedRoute, authoritiesService);
        this.activatedRoute = activatedRoute;
        this.location = location;
        this.translateService = translateService;
        this.utilsService = utilsService;
        this.authoritiesService = authoritiesService;
        this.isEdit = false;
    }
    ngOnInit() {
        this.id = this.activatedRoute.snapshot.paramMap.get('id');
        if (this.id) {
            this.isEdit = true;
        }
        this.isView = this.activatedRoute.routeConfig?.data?.actionType === ActionTypeEnum._VIEW;
    }
    back() {
        this.location.back();
    }
    onSuccessFunc = (data, onSuccessMessage) => {
        this.utilsService.onSuccessFunc(onSuccessMessage ? onSuccessMessage : 'common.default.success');
        setTimeout(() => {
            this.back();
        }, 1500);
    };
    hasAuthority() {
        return false;
    }
    getPosition(e, arr) {
        return !!arr && arr.length > 0 ? (arr.indexOf(e) + 1).toString() : '';
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BaseAddEditComponent, deps: [{ token: i1$4.ActivatedRoute }, { token: i2.Location }, { token: i1.TranslateService }, { token: UtilsService }, { token: AuthoritiesService }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: BaseAddEditComponent, isStandalone: false, selector: "BaseAddEditComponent", usesInheritance: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BaseAddEditComponent, decorators: [{
            type: Directive,
            args: [{
                    selector: 'BaseAddEditComponent',
                    standalone: false,
                }]
        }], ctorParameters: () => [{ type: i1$4.ActivatedRoute }, { type: i2.Location }, { type: i1.TranslateService }, { type: UtilsService }, { type: AuthoritiesService }] });

class MultiTranslateHttpLoader {
    http;
    resources;
    constructor(http, resources) {
        this.http = http;
        this.resources = resources;
    }
    getTranslation(lang) {
        const requests = this.resources.map(resource => {
            const path = resource.prefix + lang + resource.suffix;
            return this.http.get(path).pipe(catchError(res => {
                console.error('Something went wrong for the following translation file:', path);
                console.error(res.message);
                return of({});
            }));
        });
        return forkJoin(requests).pipe(map(responses => {
            if (!responses.length)
                return {};
            const target = {};
            for (const index in responses) {
                Object.assign(target, responses[index]);
            }
            return target;
        }));
    }
}

class MultiLanguageTablePaginator extends MatPaginatorIntl {
    translateService;
    constructor(translateService) {
        super();
        this.translateService = translateService;
        this.translateService.onLangChange.subscribe((e) => {
            this.getAndInitTranslations();
        });
        this.getAndInitTranslations();
    }
    range = '';
    getAndInitTranslations() {
        this.translateService.get('MatPaginator.itemsPerPageLabel').subscribe((res) => {
            this.itemsPerPageLabel = res;
        });
        this.translateService.get('MatPaginator.nextPageLabel').subscribe((res) => {
            this.nextPageLabel = res;
        });
        this.translateService.get('MatPaginator.previousPageLabel').subscribe((res) => {
            this.previousPageLabel = res;
        });
        this.translateService.get('MatPaginator.range').subscribe((res) => {
            this.range = ' ' + res + ' ';
        });
        this.changes.next();
    }
    getRangeLabel = (page, pageSize, length) => {
        // use style-paginator directive
        return '';
        // if (length === 0 || pageSize === 0) {
        //   return '0' + this.range + length;
        // }
        // length = Math.max(length, 0);
        // const startIndex = page * pageSize;
        // const endIndex = startIndex < length ?
        //   Math.min(startIndex + pageSize, length) :
        //   startIndex + pageSize;
        // return startIndex + 1 + ' - ' + endIndex + this.range + length;
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MultiLanguageTablePaginator, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MultiLanguageTablePaginator, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MultiLanguageTablePaginator, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: () => [{ type: i1.TranslateService }] });

class TableService {
    static DEFAULT_NO_IMAGE_AVAILABLE = 'data:image/png;base64, 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';
    static displayHeaderName(column, moduleName) {
        if (typeof (column.header) === 'string') {
            return moduleName + '.table.header.' + column.header;
        }
        return column.header ? column.header(column) : '';
    }
    static onDisplayButtonHeaderCell(buttons, button, header, index) {
        if (typeof (button.header) === 'object' && !!button.header) {
            return (button.isShowHeader ? button.isShowHeader : false) ||
                ((button.header && button.header.display) ? button.header.display(header) : false);
        }
        if (typeof (button.header) === 'string') {
            return !(!!buttons[index - 1] && typeof (buttons[index - 1].header) === 'string');
        }
        return false;
    }
    static getColumnType(col, row) {
        if (!col.columnType) {
            return ColumnTypeEnum.VIEW;
        }
        return (typeof (col.columnType) === 'function' ? col.columnType(row) : col.columnType);
    }
    static getHeaderButtonColspan(buttons, data) {
        if (!buttons) {
            return 0;
        }
        let displayCell = false;
        return buttons.reduce((colspan, button) => {
            displayCell = data.some(row => TableService.onDisplayButtonCell(button, row));
            return colspan + (displayCell ? 1 : 0);
        }, 0);
    }
    static onDisplayButtonCell(button, cell) {
        button.isShowHeader = button.isShowHeader || (button.display ? button.display(cell) : false);
        return button.display ? button.display(cell) : false;
    }
    static onDisplayCell(column, cell) {
        if (column.display) {
            column.isShowHeader = column.isShowHeader || column.display(cell);
        }
        else {
            column.isShowHeader = true;
        }
        return column.isShowHeader;
    }
    static alignCellContent(column) {
        return column.align ? column.align : AlignEnum.LEFT;
    }
    static getColspan(footer, data) {
        return typeof (footer.colspan) === 'function' ? footer.colspan(data) : footer.colspan;
    }
    static getColumnClassName(col, data = null) {
        return !!col && !!col.className ? (typeof (col.className) === 'function' ? col.className(data) : col.className) : '';
    }
    static getColumnHeaderClassName(col) {
        return !!col && !!col.headerClassName ? (typeof (col.headerClassName) === 'function' ? col.headerClassName() : col.headerClassName) : '';
    }
    static getIconType(button) {
        return button.iconType ? button.iconType : IconTypeEnum.MATERIAL_ICON;
    }
    static onErrorImgEvent(img, noImageConfigBase64) {
        img.onerror = null;
        img.src = noImageConfigBase64 ? noImageConfigBase64 : TableService.DEFAULT_NO_IMAGE_AVAILABLE;
    }
    static isButtonHeader(button) {
        return !!button.header && typeof (button.header) === 'object';
    }
    static getButtonHeader(button) {
        return this.isButtonHeader(button) ? button.header : null;
    }
    static getButtonHeaderString(button) {
        return !this.isButtonHeader(button) ? button.header : null;
    }
}

class LoaderService {
    isLoading = new BehaviorSubject(false);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LoaderService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LoaderService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

class ValidatorService {
    static invalid(control) {
        return !!control && control.dirty ? control.invalid : false;
    }
    static getErrorMessage(control, errorMessages) {
        if (!control) {
            return '';
        }
        const { errors } = control;
        const messages = errors ? Object.keys(errors).map(key => {
            const fn = errorMessages.has(key) ? errorMessages.get(key) : null;
            return fn ? fn(errors) : 'common.error.' + key;
        }) : [];
        return messages && messages.length > 0 ? messages[0] : '';
    }
    static getErrorMessageV1(control, errorMessages) {
        if (!control) {
            return '';
        }
        const { errors } = control;
        if (!errors) {
            return {};
        }
        let errKey = Object.keys(errors)[0];
        const fn = errorMessages && errorMessages.has(errKey) ? errorMessages.get(errKey) : null;
        const msg = fn ? fn(errors) : 'common.error.' + errKey;
        // const messages: string[] = errors ? Object.keys(errors).map(key => {
        //   const fn = errorMessages.has(key) ? errorMessages.get(key) : null;
        //   errKey = key;
        //   return fn ? fn(errors) : 'common.error.' + key;
        // }) : [];
        return errors && msg ? { msg, params: errors[errKey] } : {};
    }
    static generateNsMultiSelectValidators(conditions) {
        const validationFns = [];
        const validation = (control) => {
            const value = control.value;
            if (ValidatorService.getRequiredDynamic(conditions.required) && (value === undefined || value === null || value === ''
                || (!!conditions.multiple && value.length === 0))) {
                return { required: true };
            }
            return null;
        };
        validationFns.push(validation);
        return validationFns;
    }
    static generateNsInputValidators(conditions) {
        const validationFns = [];
        if (conditions.required) {
            validationFns.push(Validators.required);
        }
        if (conditions.minLength) {
            validationFns.push(Validators.minLength(conditions.minLength));
        }
        if (conditions.maxLength) {
            validationFns.push(Validators.maxLength(conditions.maxLength));
        }
        if (conditions.pattern) {
            validationFns.push(Validators.pattern(conditions.pattern));
        }
        return validationFns;
    }
    static generateNsAutocompleteValidators(conditions) {
        const validationFns = [];
        if (conditions.required) {
            validationFns.push(Validators.required);
        }
        return validationFns;
    }
    static getMinMaxDynamic(minOrMax) {
        return minOrMax !== null ? typeof (minOrMax) === 'function' ? minOrMax() : minOrMax : null;
    }
    static generateNsCounterInputValidators(conditions) {
        const validationFns = [];
        validationFns.push(Validators.pattern(conditions.isDecimal ? '^[^-]?[0-9]+[.]?[0-9]*$' : '^[0-9]*$'));
        if (conditions.required) {
            validationFns.push(Validators.required);
        }
        if (conditions.min != undefined && conditions.min != null) {
            const validationMin = (control) => {
                return ValidatorService.customMinValueNsCounterInput(control.value, ValidatorService.getMinMaxDynamic(conditions.min));
            };
            validationFns.push(validationMin);
        }
        if (conditions.max != undefined && conditions.max != null) {
            const validationMax = (control) => {
                return ValidatorService.customMaxValueNsCounterInput(control.value, ValidatorService.getMinMaxDynamic(conditions.max));
            };
            validationFns.push(validationMax);
        }
        return validationFns;
    }
    static generateNsDatePickerValidators(conditions) {
        const validationFns = [];
        if (conditions.required) {
            validationFns.push(Validators.required);
        }
        // if (conditions.min) {
        //     validationFns.push(new NsValidator({minDate: conditions.min}).customMinDateValidator());
        // }
        // if (conditions.max) {
        //     validationFns.push(new NsValidator({maxDate: conditions.max}).customMaxDateValidator());
        // }
        return validationFns;
    }
    static getRequiredDynamic(isRequired) {
        return isRequired ? typeof (isRequired) === 'boolean' ? isRequired : isRequired() : false;
    }
    static generateNsDateRangePickerValidators(conditions) {
        const validationFns = [];
        // if (NsValidator.getRequiredDynamic(conditions.requiredFromDate)
        //     || NsValidator.getRequiredDynamic(conditions.requiredToDate)) {
        const validation = (control) => {
            const range = control.value;
            if (!range?.fromDate && ValidatorService.getRequiredDynamic(conditions.requiredFromDate)) {
                return { requiredFromDate: true };
            }
            if (!range?.toDate && ValidatorService.getRequiredDynamic(conditions.requiredToDate)) {
                return { requiredToDate: true };
            }
            return null;
        };
        validationFns.push(validation);
        // }
        return validationFns;
    }
    // customMinDateValidator(): ValidatorFn {
    //     return this.customMinDateValidatorControl;
    // }
    static customMinDateValidatorControl(value, minDate) {
        if (!minDate || !value) {
            return null;
        }
        let date = value instanceof Date ? value : new Date(value.replace(' ', 'T'));
        if (date < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate(), 0, 0, 0)) {
            return { min: { valid: false, minValue: minDate, actual: date } };
        }
        return null;
    }
    // customMaxDateValidator(): ValidatorFn {
    //     return this.customMaxDateValidatorControl;
    // }
    static customMaxDateValidatorControl(value, maxDate) {
        if (!maxDate || !value) {
            return null;
        }
        let date = value instanceof Date ? value : new Date(value.replace(' ', 'T').replace('Z', ''));
        if (date > new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate(), 0, 0, 0)) {
            return { max: { valid: false, maxValue: maxDate, actual: date } };
        }
        return null;
    }
    static getRequired(column) {
        return column.isRequired ? typeof (column.isRequired) === 'boolean' ? column.isRequired : column.isRequired() : false;
    }
    static getIsDecimal(column) {
        return column.isDecimal ? typeof (column.isDecimal) === 'boolean' ? column.isDecimal : column.isDecimal() : false;
    }
    static customMinValueNsCounterInput(value, min) {
        if (!isNaN(Number(value)) && min !== null && value < min) {
            return { min: { min: min, actual: value } };
        }
        return null;
    }
    static customMaxValueNsCounterInput(value, max) {
        if (!isNaN(Number(value)) && max !== null && value > max) {
            return { max: { max: max, actual: value } };
        }
        return null;
    }
    static generateNsSmartTableValidators(conditions) {
        const validator = (control) => {
            let errors = null;
            if (control) {
                const controlValueLength = control.value ? control.value.length : 0;
                if (conditions.minRow > controlValueLength) {
                    return { minRow: { valid: false, min: conditions.minRow, actual: controlValueLength } };
                }
                if (conditions.maxRow < controlValueLength) {
                    return { maxRow: { valid: false, max: conditions.maxRow, actual: controlValueLength } };
                }
                if (!control.value) {
                    return null;
                }
                control.value.forEach((row) => {
                    if (errors || !conditions.columns) {
                        return;
                    }
                    conditions.columns.forEach((column) => {
                        if (errors) {
                            return;
                        }
                        const tempControl = new FormControl();
                        tempControl.setValue(row[column.columnDef]);
                        if (TableService.getColumnType(column, row) === ColumnTypeEnum.MULTI_SELECT_AUTOCOMPLETE) {
                            if (ValidatorService.getRequired(column)) {
                                tempControl.setValidators(Validators.required);
                            }
                        }
                        else if (TableService.getColumnType(column, row) === ColumnTypeEnum.INPUT_COUNTER) {
                            tempControl.setValidators(ValidatorService.generateNsCounterInputValidators({
                                required: ValidatorService.getRequired(column),
                                min: null,
                                max: null,
                                isDecimal: ValidatorService.getIsDecimal(column),
                            }));
                        }
                        else if (TableService.getColumnType(column, row) === ColumnTypeEnum.DATE_PICKER) {
                            tempControl.setValidators(ValidatorService.generateNsDatePickerValidators({
                                required: ValidatorService.getRequired(column),
                                min: null,
                                max: null,
                            }));
                        }
                        else if (TableService.getColumnType(column, row) === ColumnTypeEnum.INPUT) {
                            tempControl.setValidators(ValidatorService.generateNsInputValidators({
                                required: ValidatorService.getRequired(column),
                                maxLength: column.max ? column.max(row) : undefined,
                                minLength: column.min ? column.min(row) : undefined,
                                pattern: undefined,
                            }));
                        }
                        tempControl.updateValueAndValidity();
                        if (TableService.getColumnType(column, row) === ColumnTypeEnum.DATE_PICKER) {
                            const errorsArr = [];
                            if (tempControl.errors) {
                                errorsArr.push(tempControl.errors);
                            }
                            if (ValidatorService.customMinDateValidatorControl(tempControl.value, column.min ? column.min(row) : null)) {
                                errorsArr.push(ValidatorService.customMinDateValidatorControl(tempControl.value, column.min ? column.min(row) : null));
                            }
                            if (ValidatorService.customMaxDateValidatorControl(tempControl.value, column.max ? column.max(row) : null)) {
                                errorsArr.push(ValidatorService.customMaxDateValidatorControl(tempControl.value, column.max ? column.max(row) : null));
                            }
                            if (errorsArr.length > 0) {
                                tempControl.setErrors(errorsArr);
                            }
                        }
                        if (TableService.getColumnType(column, row) === ColumnTypeEnum.INPUT_COUNTER) {
                            const errorsArr = [];
                            if (tempControl.errors) {
                                errorsArr.push(tempControl.errors);
                            }
                            if (ValidatorService.customMinValueNsCounterInput(tempControl.value, column.min ? column.min(row) : null)) {
                                errorsArr.push(ValidatorService.customMinValueNsCounterInput(tempControl.value, column.min ? column.min(row) : null));
                            }
                            if (ValidatorService.customMaxValueNsCounterInput(tempControl.value, column.max ? column.max(row) : null)) {
                                errorsArr.push(ValidatorService.customMaxValueNsCounterInput(tempControl.value, column.max ? column.max(row) : null));
                            }
                            if (errorsArr.length > 0) {
                                tempControl.setErrors(errorsArr);
                            }
                        }
                        tempControl.markAllAsTouched();
                        errors = tempControl.errors;
                    });
                });
            }
            return errors;
        };
        return validator;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ValidatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ValidatorService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ValidatorService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

class CvaCounterInputComponent {
    injector;
    label = '';
    placeholder = '';
    suffixText = '';
    hint = '';
    value = 0;
    disabled = false;
    required = false;
    errorMessages = new Map();
    min = null;
    max = null;
    error;
    isDecimal = false;
    isLabelOutside = false;
    isFloatLabel = true;
    /* percent label outside css */
    percentOfLabelOutside = 25;
    alignNumber = AlignEnum.RIGHT;
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    onChange = new EventEmitter();
    onEnter = new EventEmitter();
    // Cái này là để gắn khi nó là FormControl trong 1 FormGroup
    formControl;
    constructor(injector, ngControl) {
        this.injector = injector;
        if (ngControl) {
            // ngControl là parent FormControl
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    get NsValidator() {
        return ValidatorService;
    }
    get counterValue() {
        return this.value;
    }
    set counterValue(val) {
        this.writeValue(val);
    }
    ngOnChanges(changes) {
        if ('value' in changes) {
            this.value = changes.value.currentValue;
            this.writeValue(this.value);
        }
    }
    ngOnInit() {
        this.callValidator();
    }
    getMinNumber() {
        return typeof (this.min) === 'function' ? this.min() : this.min;
    }
    getMaxNumber() {
        return typeof (this.max) === 'function' ? this.max() : this.max;
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.formControl) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.formControl = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.formControl = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.formControl) {
                this.formControl.setValidators(ValidatorService.generateNsCounterInputValidators({
                    required: this.required,
                    min: this.min,
                    max: this.max,
                    isDecimal: this.isDecimal,
                }));
            }
        }
        if (this.formControl) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.formControl.setValue(this.value);
            }
            // Nếu là parent FormControl rồi thì kệ
            this.formControl.updateValueAndValidity();
            if (!this.formControl.errors) {
                const minErr = ValidatorService.customMinValueNsCounterInput(this.value, this.getMinNumber());
                if (minErr) {
                    this.formControl.setErrors(minErr);
                }
                const maxErr = ValidatorService.customMaxValueNsCounterInput(this.value, this.getMaxNumber());
                if (maxErr) {
                    this.formControl.setErrors(maxErr);
                }
                this.formControl.markAllAsTouched();
                if (!this.isFormControl) {
                    this.formControl.markAsDirty();
                }
            }
        }
    }
    writeValue(value) {
        if (value !== undefined) {
            this.value = value;
            this.propagateChange(this.value);
            this.callValidator();
            this.onChange.emit(this.value);
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaCounterInputComponent, deps: [{ token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaCounterInputComponent, isStandalone: false, selector: "cva-counter-input", inputs: { label: "label", placeholder: "placeholder", suffixText: "suffixText", hint: "hint", value: "value", disabled: "disabled", required: "required", errorMessages: "errorMessages", min: "min", max: "max", error: "error", isDecimal: "isDecimal", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", percentOfLabelOutside: "percentOfLabelOutside", alignNumber: "alignNumber", isFormControl: "isFormControl" }, outputs: { onChange: "onChange", onEnter: "onEnter" }, usesOnChanges: true, ngImport: i0, template: `
    <!-- css labelOutside trong base.theme-->
    <div class="cva-counter-input"
         [ngClass]="{'labelOutside': !!isLabelOutside, 'float_label': !!isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && !!isFloatLabel">{{ (label ? label : placeholder) | translate }}</mat-label>
        <div class="input-area">
          <input matInput type="number" [(ngModel)]="counterValue" #nsCounterInput="ngModel"
                 style="text-align:{{alignNumber}}"
                 [disabled]="disabled" [required]="required"
                 (keydown.enter)="onEnter.emit()"
                 [placeholder]="placeholder|translate"
                 autocomplete="off"
                 pattern="{{isDecimal ? '^[^-]?[0-9]+[.]?[0-9]*$' : '^[0-9]*$'}}" min="{{min}}" max="{{max}}" />
          <span *ngIf="!!suffixText" class="input-suffix"
                matSuffix>{{ suffixText }}</span>
        </div>
        <mat-hint *ngIf="!NsValidator.invalid(formControl)">
          {{ hint | translate }}
        </mat-hint>
        <mat-hint style="color: red" *ngIf="NsValidator.invalid(formControl)">
          {{ NsValidator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </mat-form-field>
    </div>
  `, isInline: true, 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: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1$2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$2.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaCounterInputComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-counter-input',
                    standalone: false,
                    template: `
    <!-- css labelOutside trong base.theme-->
    <div class="cva-counter-input"
         [ngClass]="{'labelOutside': !!isLabelOutside, 'float_label': !!isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && !!isFloatLabel">{{ (label ? label : placeholder) | translate }}</mat-label>
        <div class="input-area">
          <input matInput type="number" [(ngModel)]="counterValue" #nsCounterInput="ngModel"
                 style="text-align:{{alignNumber}}"
                 [disabled]="disabled" [required]="required"
                 (keydown.enter)="onEnter.emit()"
                 [placeholder]="placeholder|translate"
                 autocomplete="off"
                 pattern="{{isDecimal ? '^[^-]?[0-9]+[.]?[0-9]*$' : '^[0-9]*$'}}" min="{{min}}" max="{{max}}" />
          <span *ngIf="!!suffixText" class="input-suffix"
                matSuffix>{{ suffixText }}</span>
        </div>
        <mat-hint *ngIf="!NsValidator.invalid(formControl)">
          {{ hint | translate }}
        </mat-hint>
        <mat-hint style="color: red" *ngIf="NsValidator.invalid(formControl)">
          {{ NsValidator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </mat-form-field>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { label: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], suffixText: [{
                type: Input
            }], hint: [{
                type: Input
            }], value: [{
                type: Input
            }], disabled: [{
                type: Input
            }], required: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], min: [{
                type: Input
            }], max: [{
                type: Input
            }], error: [{
                type: Input
            }], isDecimal: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], alignNumber: [{
                type: Input
            }], isFormControl: [{
                type: Input
            }], onChange: [{
                type: Output
            }], onEnter: [{
                type: Output
            }] } });

class StylePaginatorDirective {
    config;
    matPag;
    vr;
    ren;
    _currentPage = 1;
    _pageGapTxt = '...';
    _rangeStart;
    _rangeEnd;
    _buttons = [];
    _showTotalPages = 5;
    get showTotalPages() {
        return this._showTotalPages;
    }
    set showTotalPages(value) {
        this._showTotalPages = value % 2 == 0 ? value + 1 : value;
    }
    $paging;
    get paging() {
        return this.$paging;
    }
    set paging(paging) {
        if (paging) {
            this.$paging = paging;
            // pageIndex = pageNumber -1
            this.switchPage(paging.pageNumber - 1, false);
        }
    }
    pagingChangeEvent = new EventEmitter(); // PageEvent
    constructor(config, matPag, vr, ren) {
        this.config = config;
        this.matPag = matPag;
        this.vr = vr;
        this.ren = ren;
        //Sub to rerender buttons when next page and last page is used or choose pageSize
        this.matPag.page.subscribe((pageEvent) => {
            if (this.paging) {
                this.paging.pageSize = pageEvent.pageSize;
            }
            this.switchPage(pageEvent.pageIndex, true);
        });
    }
    buildPageNumbers() {
        const actionContainer = this.vr.element.nativeElement.querySelector('div.mat-paginator-range-actions');
        const nextPageNode = this.vr.element.nativeElement.querySelector('button.mat-paginator-navigation-next');
        // remove buttons before creating new ones
        if (this._buttons.length > 0) {
            this._buttons.forEach(button => {
                this.ren.removeChild(actionContainer, button);
            });
            //Empty state array
            this._buttons.length = 0;
        }
        //initialize next page and last page buttons
        if (this._buttons.length == 0) {
            let nodeArray = this.vr.element.nativeElement?.childNodes[0]?.childNodes[0]
                ?.childNodes[2]?.childNodes;
            if (nodeArray) {
                setTimeout(() => {
                    for (let i = 0; i < nodeArray.length; i++) {
                        if (nodeArray[i].nodeName === 'BUTTON') {
                            if (nodeArray[i].disabled) {
                                this.ren.setStyle(nodeArray[i], 'background-color', 'rgba(190, 130, 130, 1)');
                                this.ren.setStyle(nodeArray[i], 'color', 'white');
                                this.ren.setStyle(nodeArray[i], 'margin', '.5%');
                            }
                            else {
                                this.ren.setStyle(nodeArray[i], 'background-color', 'rgba(255, 0, 0, 1)');
                                this.ren.setStyle(nodeArray[i], 'color', 'white');
                                this.ren.setStyle(nodeArray[i], 'margin', '.6%');
                            }
                        }
                    }
                });
            }
        }
        let dots = false;
        if ((!!this._rangeStart || this._rangeStart === 0) && (!!this._rangeEnd || this._rangeEnd === 0)) {
            for (let i = 0; i < this.matPag.getNumberOfPages(); i = i + 1) {
                if ((i < this._showTotalPages &&
                    this._currentPage < this._showTotalPages &&
                    i > this._rangeStart) ||
                    (i >= this._rangeStart && i <= this._rangeEnd)) {
                    this.ren.insertBefore(actionContainer, this.createButton(i, this.matPag.pageIndex), nextPageNode);
                }
                else {
                    if (i > this._rangeEnd && !dots) {
                        // if (!isNaN(i)) {
                        //     this.ren.insertBefore(
                        //         actionContainer,
                        //         this.createButton(this._pageGapTxt, this.matPag.pageIndex),
                        //         nextPageNode
                        //     );
                        //     dots = true;
                        // }
                    }
                }
            }
        }
    }
    createButton(i, pageIndex) {
        const linkBtn = this.ren.createElement('mat-button');
        this.ren.addClass(linkBtn, 'mat-mini-fab');
        this.ren.setStyle(linkBtn, 'margin', '1%');
        const pagingTxt = isNaN(i) ? this._pageGapTxt : +(i + 1);
        const text = this.ren.createText(pagingTxt + '');
        this.ren.addClass(linkBtn, 'mat-custom-page');
        switch (i) {
            case pageIndex:
                this.ren.setAttribute(linkBtn, 'disabled', 'disabled');
                break;
            case this._pageGapTxt:
                // this.ren.listen(linkBtn, "click", () => {
                //     this.switchPage(this._currentPage + this._showTotalPages);
                // });
                break;
            default:
                this.ren.listen(linkBtn, 'click', () => {
                    this.switchPage(i, true);
                });
                break;
        }
        this.ren.appendChild(linkBtn, text);
        //Add button to private array for state
        this._buttons.push(linkBtn);
        return linkBtn;
    }
    initPageRange() {
        this._rangeStart = this._currentPage - this._showTotalPages / 2;
        this._rangeEnd = this._currentPage + this._showTotalPages / 2;
        this.buildPageNumbers();
    }
    switchPage(i, isEvent) {
        this._currentPage = i;
        this.matPag.pageIndex = i;
        if (isEvent) {
            this.pagingChangeEvent.emit({
                pageIndex: i,
                pageSize: this.paging ? this.paging.pageSize : this.config.PAGE_SIZE,
            });
        }
        this.initPageRange();
    }
    ngAfterViewInit() {
        this.initPageRange();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: StylePaginatorDirective, deps: [{ token: InjectTokenNextSolutionsConfig }, { token: i1$5.MatPaginator, host: true, optional: true, self: true }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: StylePaginatorDirective, isStandalone: false, selector: "[style-paginator]", inputs: { showTotalPages: "showTotalPages", paging: "paging" }, outputs: { pagingChangeEvent: "pagingChangeEvent" }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: StylePaginatorDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[style-paginator]',
                    standalone: false,
                }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [InjectTokenNextSolutionsConfig]
                }] }, { type: i1$5.MatPaginator, decorators: [{
                    type: Host
                }, {
                    type: Self
                }, {
                    type: Optional
                }] }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }], propDecorators: { showTotalPages: [{
                type: Input
            }], paging: [{
                type: Input
            }], pagingChangeEvent: [{
                type: Output
            }] } });

class CvaHeaderExpandButtonComponent {
    expandHeaderButton;
    columns = [];
    moduleName = '';
    onChange = new EventEmitter();
    expandDisplayCols = {};
    constructor() {
    }
    get ColumnTypes() {
        return ColumnTypeEnum;
    }
    get IconTypes() {
        return IconTypeEnum;
    }
    get TableService() {
        return TableService;
    }
    ngOnInit() {
        this.columns.forEach(col => {
            this.expandDisplayCols[col.columnDef] = !(col.isExpandOptionColumn ? col.isExpandOptionColumn() : false);
            col.isExpandOptionColumn = () => !this.expandDisplayCols[col.columnDef];
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaHeaderExpandButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaHeaderExpandButtonComponent, isStandalone: false, selector: "cva-header-expand-button", inputs: { expandHeaderButton: "expandHeaderButton", columns: "columns", moduleName: "moduleName" }, outputs: { onChange: "onChange" }, ngImport: i0, template: `
    <button mat-icon-button
            class="expand-column-header-button"
            color="{{expandHeaderButton?.color}}"
            [matMenuTriggerFor]="menu"
            matTooltip="{{((expandHeaderButton && expandHeaderButton.title) ? expandHeaderButton.title : '') | translate}}"
    >
      <mat-icon *ngIf="expandHeaderButton && TableService.getIconType(expandHeaderButton)===IconTypes.MATERIAL_ICON">
        {{ expandHeaderButton?.icon }}
      </mat-icon>
      <i *ngIf="expandHeaderButton && TableService.getIconType(expandHeaderButton) === IconTypes.FONT_AWESOME"
         class="{{expandHeaderButton?.icon}}"></i>
    </button>


    <mat-menu class="menu-expand-column" #menu="matMenu">
      <div class="header-menu-expand" fxLayout fxLayoutAlign="space-between center">
        <mat-label>{{ 'common.expand.menu.header.label' | translate }}</mat-label>
        <button mat-flat-button>{{ 'common.label.done' | translate }}</button>
      </div>
      <div class="choose-area" (click)="$event.stopPropagation()">
        <div mat-menu-item *ngFor="let col of columns">
          <ng-container *ngIf="col.columnType!==ColumnTypes.CHECKBOX">
            <mat-checkbox style="width: 100%"
                          [(ngModel)]="expandDisplayCols[col.columnDef]"
                          [value]="col.columnDef"
                          (change)="this.onChange.emit(this.expandDisplayCols)">
              {{ (moduleName + '.table.header.' + col.header) | translate }}
            </mat-checkbox>
          </ng-container>
        </div>
      </div>
    </mat-menu>

  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i8$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaHeaderExpandButtonComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-header-expand-button',
                    standalone: false,
                    template: `
    <button mat-icon-button
            class="expand-column-header-button"
            color="{{expandHeaderButton?.color}}"
            [matMenuTriggerFor]="menu"
            matTooltip="{{((expandHeaderButton && expandHeaderButton.title) ? expandHeaderButton.title : '') | translate}}"
    >
      <mat-icon *ngIf="expandHeaderButton && TableService.getIconType(expandHeaderButton)===IconTypes.MATERIAL_ICON">
        {{ expandHeaderButton?.icon }}
      </mat-icon>
      <i *ngIf="expandHeaderButton && TableService.getIconType(expandHeaderButton) === IconTypes.FONT_AWESOME"
         class="{{expandHeaderButton?.icon}}"></i>
    </button>


    <mat-menu class="menu-expand-column" #menu="matMenu">
      <div class="header-menu-expand" fxLayout fxLayoutAlign="space-between center">
        <mat-label>{{ 'common.expand.menu.header.label' | translate }}</mat-label>
        <button mat-flat-button>{{ 'common.label.done' | translate }}</button>
      </div>
      <div class="choose-area" (click)="$event.stopPropagation()">
        <div mat-menu-item *ngFor="let col of columns">
          <ng-container *ngIf="col.columnType!==ColumnTypes.CHECKBOX">
            <mat-checkbox style="width: 100%"
                          [(ngModel)]="expandDisplayCols[col.columnDef]"
                          [value]="col.columnDef"
                          (change)="this.onChange.emit(this.expandDisplayCols)">
              {{ (moduleName + '.table.header.' + col.header) | translate }}
            </mat-checkbox>
          </ng-container>
        </div>
      </div>
    </mat-menu>

  `,
                }]
        }], ctorParameters: () => [], propDecorators: { expandHeaderButton: [{
                type: Input
            }], columns: [{
                type: Input
            }], moduleName: [{
                type: Input
            }], onChange: [{
                type: Output
            }] } });

class SecureImgPipe {
    http;
    sanitizer;
    constructor(http, sanitizer) {
        this.http = http;
        this.sanitizer = sanitizer;
    }
    transform(url) {
        return this.http
            .get(url, {
            headers: new HttpHeaders().set('is_image', 'true'),
            responseType: 'blob',
        })
            .pipe(map(value => this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(value))));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SecureImgPipe, deps: [{ token: i1$3.HttpClient }, { token: i2$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.1.5", ngImport: i0, type: SecureImgPipe, isStandalone: false, name: "secure" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SecureImgPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'secure',
                    standalone: false,
                }]
        }], ctorParameters: () => [{ type: i1$3.HttpClient }, { type: i2$2.DomSanitizer }] });

class CvaTableComponent {
    config;
    cdRef;
    loaderService;
    moduleName = '';
    varPaging;
    results = new MatTableDataSource([]);
    columns = [];
    buttons = [];
    showTotalPages = 5;
    expandHeaderButton;
    pageSizeOptions;
    pagingChange = new EventEmitter(true);
    clickAction = new EventEmitter();
    onRowClickAction = new EventEmitter();
    onChangeDisplayColumn = new EventEmitter();
    selectAllChecked = false;
    goToPageNumber = 1;
    errorMsg = new Map()
        .set('min', () => '')
        .set('max', () => '')
        .set('pattern', () => '')
        .set('required', () => '');
    // display status object column in table
    expandDisplayCols = {};
    buttonColspan = 0;
    constructor(config, 
    /*public domSanitizer: DomSanitizer,*/
    cdRef, loaderService) {
        this.config = config;
        this.cdRef = cdRef;
        this.loaderService = loaderService;
        this.pageSizeOptions = this.config.PAGE_SIZE_OPTIONS;
        this.varPaging = new TablePagingRequestModel();
        this.varPaging.pageSize = this.config.PAGE_SIZE;
        this.varPaging.pageNumber = 1;
        this.varPaging.totalElements = 0;
    }
    set paging(value) {
        if (value) {
            this.varPaging = value;
        }
    }
    get displayedColumns() {
        let columnsDef = this.columns.map(c => c.columnDef);
        if (this.buttons) {
            columnsDef = columnsDef.concat(this.buttons.map(b => b.columnDef));
        }
        // if (!!this.expandHeaderButton) {
        //     columnsDef = columnsDef.concat(this.expandHeaderButton.columnDef);
        // }
        return columnsDef;
    }
    get ColumnTypes() {
        return ColumnTypeEnum;
    }
    get IconTypes() {
        return IconTypeEnum;
    }
    get AlignEnum() {
        return AlignEnum;
    }
    get TableService() {
        return TableService;
    }
    isExpandColumn(col) {
        return !!col.isExpandOptionColumn ? col.isExpandOptionColumn() : false;
    }
    getPage(pageable) {
        this.varPaging.pageNumber = pageable.pageIndex + 1;
        this.varPaging.pageSize = pageable.pageSize;
        this.pagingChange.emit(this.varPaging);
        this.toggleSelect(null, null);
        this.goToPageNumber = this.varPaging.pageNumber;
    }
    onClick(action, result) {
        const buttonClickEvent = new ButtonClickEvent(action, result);
        this.clickAction.emit(buttonClickEvent);
    }
    ngOnInit() {
        if (!this.varPaging) {
            this.varPaging = new TablePagingRequestModel();
            this.varPaging.pageSize = this.config.PAGE_SIZE;
            this.varPaging.pageNumber = 1;
            this.varPaging.totalElements = 0;
            this.pagingChange.emit(this.varPaging);
        }
        // setup binding object with column
        this.columns.forEach(col => {
            this.expandDisplayCols[col.columnDef] = !(col.isExpandOptionColumn ? col.isExpandOptionColumn() : false);
            col.isExpandOptionColumn = () => !this.expandDisplayCols[col.columnDef];
        });
    }
    onRowClick(result, index) {
        const buttonClickModel = new ButtonClickEvent('onRowClick', result, index);
        this.onRowClickAction.emit(buttonClickModel);
    }
    onDisplayHeaderCell(column) {
        return (column.isShowHeader ? column.isShowHeader : !this.hasData()) && !this.isExpandColumn(column);
    }
    onDisplayCell(column, cell) {
        return TableService.onDisplayCell(column, cell) && !this.isExpandColumn(column);
    }
    toggleSelectAll(val, col) {
        this.results.data.forEach(v => {
            v.checked = val.checked;
        });
        if (col.onHeaderCellValueChange) {
            col.onHeaderCellValueChange(val.checked);
        }
    }
    toggleSelect(val, result, column) {
        let count = 0;
        this.results.data.forEach(v => {
            if (v.checked) {
                count++;
            }
        });
        this.selectAllChecked = count === this.results.data.length;
        if (column && column.onCellValueChange) {
            column.onCellValueChange(result);
        }
    }
    ngAfterViewChecked() {
        this.getHeaderButtonColspan();
        this.cdRef.detectChanges();
    }
    hasData() {
        return this.results && this.results.data && this.results.data.length > 0;
    }
    getTotalPage() {
        if (!this.varPaging) {
            return 0;
        }
        return (this.varPaging.totalElements % this.varPaging.pageSize) === 0
            ? Math.floor(this.varPaging.totalElements / this.varPaging.pageSize)
            : Math.floor((this.varPaging.totalElements / this.varPaging.pageSize) + 1);
    }
    goToPage() {
        if (this.goToPageNumber) {
            this.getPage({ pageIndex: this.goToPageNumber - 1, pageSize: this.varPaging.pageSize });
        }
    }
    getHeaderButtonColspan() {
        this.buttonColspan = TableService.getHeaderButtonColspan(this.buttons, this.results.data);
        return this.buttonColspan;
    }
    onChangeGoToPageNumber($event) {
        if ($event === null || Number.isNaN($event) || !Number.isSafeInteger($event)) {
            this.goToPageNumber = 1;
            return;
        }
        if (this.goToPageNumber > this.getTotalPage()) {
            this.goToPageNumber = this.getTotalPage();
        }
        const item = window.document.querySelector('.go-to-page cva-counter-input .mat-mdc-form-field-infix input');
        if (item && item.closest) {
            const itemClosest = item.closest('.mat-mdc-form-field-infix');
            if (itemClosest) {
                itemClosest.style.width = ($event.toString().length * 15 + 20) + 'px';
            }
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaTableComponent, deps: [{ token: InjectTokenNextSolutionsConfig }, { token: i0.ChangeDetectorRef }, { token: LoaderService }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaTableComponent, isStandalone: false, selector: "cva-table", inputs: { moduleName: "moduleName", results: "results", columns: "columns", buttons: "buttons", showTotalPages: "showTotalPages", expandHeaderButton: "expandHeaderButton", paging: "paging" }, outputs: { pagingChange: "pagingChange", clickAction: "clickAction", onRowClickAction: "onRowClickAction", onChangeDisplayColumn: "onChangeDisplayColumn" }, providers: [
            { provide: MatPaginatorIntl, useClass: MultiLanguageTablePaginator },
        ], ngImport: i0, template: `
    <div class="table-responsive">
      <ng-container *ngIf="!!expandHeaderButton">
        <cva-header-expand-button [moduleName]="moduleName" [expandHeaderButton]="expandHeaderButton"
                                  [columns]="columns" (onChange)="this.onChangeDisplayColumn.emit($event)">
        </cva-header-expand-button>
      </ng-container>
      <table mat-table #table [dataSource]="results" class="mat-elevation-z8 cva-table">
        <ng-container *ngFor="let column of columns" matColumnDef="{{column.columnDef}}">
          <ng-container *matHeaderCellDef>
            <th mat-header-cell [ngClass]="TableService.getColumnHeaderClassName(column)"
                *ngIf="onDisplayHeaderCell(column)"
                [ngSwitch]="TableService.getColumnType(column, null)">
              <div fxLayout="row" *ngSwitchDefault
                   class="viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   [fxLayoutAlign]="column.alignHeader ? column.alignHeader : TableService.alignCellContent(column)">
                {{ TableService.displayHeaderName(column, moduleName) | translate }}
              </div>
              <mat-checkbox *ngSwitchCase="ColumnTypes.CHECKBOX"
                            color="primary" class="box-select-all" [(ngModel)]="selectAllChecked"
                            (change)="toggleSelectAll($event, column)"
                            [fxLayoutAlign]="column.alignHeader ? column.alignHeader : TableService.alignCellContent(column)">
              </mat-checkbox>
            </th>
          </ng-container>
          <ng-container *matCellDef="let result;">
            <td mat-cell [ngClass]="TableService.getColumnClassName(column, result)"
                *ngIf="onDisplayCell(column, result)"
                [ngSwitch]="TableService.getColumnType(column, result)">
              <div title="{{column.title(result)}}" *ngSwitchDefault
                   class="{{TableService.getColumnClassName(column, result)}} viewData"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)">
                {{ column.cell(result) }}
              </div>
              <ng-container *ngSwitchCase="ColumnTypes.BUTTON">
                <div *ngIf="!!column.button"
                     class="{{TableService.getColumnClassName(column, result)}}"
                     fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                     (click)="$event.stopPropagation()">
                  <button mat-icon-button color="{{column.button.color}}"
                          (click)="onClick(column.button.click, result)"
                          disabled="{{column.button.disabled ? column.button.disabled(result) : false}}"
                          matTooltip="{{(column.button.title ? column.button.title : '') | translate}}"
                          class="{{column.button.className}}" [ngSwitch]="TableService.getIconType(column.button)">
                    <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ column.button.icon }}</mat-icon>
                    <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{column.button.icon}}"></i>
                  </button>
                </div>
              </ng-container>
              <div class="link viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.LINK"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <a [routerLink]="[column.link(result)]">{{ column.cell(result) }}</a>
              </div>

              <div class="label-status viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.STYLE_CSS"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <span [style]="column.style(result)">{{ column.cell(result) }}</span>
              </div>

              <div class="img-view viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result) | secure | async" #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div class="img-view viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG_NO_SECURE"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result)" #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div *ngSwitchCase="ColumnTypes.BASE64"
                   class="img-view viewData"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="'data:image/png;base64,'+column.cell(result)"
                     #base64ImgRef
                     (error)="TableService.onErrorImgEvent(base64ImgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <ng-container *ngSwitchCase="ColumnTypes.CHECKBOX">
                <mat-checkbox [(ngModel)]="result[column.columnDef]" color="primary"
                              *ngIf="column.display ? column.display(result) : true"
                              [disabled]="column.disabled ? column.disabled(result) : false"
                              (change)="toggleSelect($event, result, column)"
                              [fxLayoutAlign]="TableService.alignCellContent(column)">
                </mat-checkbox>
              </ng-container>
            </td>
          </ng-container>
        </ng-container>

        <ng-container *ngFor="let button of buttons; let i = index" matColumnDef="{{button.columnDef}}">
          <ng-container *matHeaderCellDef="let header">
            <!--                    [fxFlex]="(isButtonHeader(button) ? headerButtonWidthDefault : getHeaderButtonWidth(i)) + 'px' "-->
            <!--                    [fxFlex]="getHeaderButtonWidth(i) + 'px' "-->
            <th mat-header-cell [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonHeaderCell(buttons, button, header, i) && !!buttonColspan"
                (click)="$event.stopPropagation()"
                [attr.colspan]="buttonColspan"
            >
              <ng-container *ngIf="TableService.getButtonHeader(button) as btnHeader">
                <button mat-icon-button
                        class="{{button.className}}"
                        *ngIf="((btnHeader && btnHeader.display) ? btnHeader.display(header) : false) "
                        [disabled]="((btnHeader && $any(btnHeader).disabled) ? $any(btnHeader).disabled(header) : false) "
                        color="{{$any(btnHeader).color}}"
                        (click)="onClick($any(btnHeader).click, null)"
                        matTooltip="{{((btnHeader && $any(btnHeader).title) ? $any(btnHeader).title : '') | translate}}"
                        [ngSwitch]="TableService.getIconType($any(btnHeader))">
                  <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ $any(btnHeader).icon }}</mat-icon>
                  <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{$any(btnHeader).icon}}"></i>
                </button>
              </ng-container>
              <ng-container *ngIf="TableService.getButtonHeaderString(button) as btnHeader">
                <div title="{{$any(btnHeader) | translate}}"
                     class="viewData"
                     fxLayout="row"
                     fxLayoutAlign="{{button.alignHeader ? button.alignHeader : AlignEnum.LEFT}} center">
                  {{ $any(btnHeader) | translate }}
                </div>
              </ng-container>
            </th>

          </ng-container>
          <ng-container *matCellDef="let cell">
            <!--                     [fxFlex]="headerButtonWidthDefault + 'px'"-->
            <td mat-cell [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonCell(button, cell)"
                (click)="$event.stopPropagation()">
              <button mat-icon-button color="{{button.color}}"
                      (click)="onClick(button.click, cell)"
                      disabled="{{button.disabled ? button.disabled(cell) : false}}"
                      matTooltip="{{(button.title ? button.title : '') | translate}}"
                      class="{{button.className}}" [ngSwitch]="TableService.getIconType(button)">
                <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ button.icon }}</mat-icon>
                <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{button.icon}}"></i>
              </button>
            </td>
          </ng-container>
        </ng-container>


        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let result; columns: displayedColumns; let i = index"
            [ngClass]="result.className"
            (click)="onRowClick(result, i)"></tr>
      </table>
      <div *ngIf="!(loaderService.isLoading | async)">
        <div class="paging"
             *ngIf="hasData()"
             fxLayout fxLayoutAlign="space-between center">
          <mat-paginator style-paginator
                         [showTotalPages]="showTotalPages"
                         [paging]="varPaging"
                         (pagingChangeEvent)="getPage($event)"
                         [length]="varPaging.totalElements"
                         [pageSize]="varPaging.pageSize"
                         [pageSizeOptions]="pageSizeOptions"
                         [pageIndex]="varPaging.pageNumber - 1">
          </mat-paginator>
          <div class="go-to-page"
               fxLayout fxLayoutGap="0.3rem" fxLayoutAlign="start baseline">
            <mat-label>{{ 'common.gotopage' | translate }}</mat-label>
            <cva-counter-input [(ngModel)]="goToPageNumber"
                               (ngModelChange)="onChangeGoToPageNumber($event)"
                               (onEnter)="goToPage()"
                               [max]="getTotalPage() ? getTotalPage() : 1"
                               [min]="1"
                               [isFloatLabel]="false"
                               [errorMessages]="errorMsg"
            ></cva-counter-input>
            <mat-label style="white-space: nowrap">{{ '/' + getTotalPage() }}</mat-label>
            <button mat-flat-button
                    [disabled]="goToPageNumber < 1 || goToPageNumber > getTotalPage()"
                    (click)="goToPage()">{{ 'common.go' | translate }}
            </button>
          </div>
          <h2 *ngIf="!hasData()">{{ 'common.no.records.found' | translate }}</h2>
        </div>
      </div>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i1$5.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: i8$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutGapDirective, selector: "  [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md],  [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md],  [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm],  [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "component", type: CvaCounterInputComponent, selector: "cva-counter-input", inputs: ["label", "placeholder", "suffixText", "hint", "value", "disabled", "required", "errorMessages", "min", "max", "error", "isDecimal", "isLabelOutside", "isFloatLabel", "percentOfLabelOutside", "alignNumber", "isFormControl"], outputs: ["onChange", "onEnter"] }, { kind: "directive", type: StylePaginatorDirective, selector: "[style-paginator]", inputs: ["showTotalPages", "paging"], outputs: ["pagingChangeEvent"] }, { kind: "component", type: CvaHeaderExpandButtonComponent, selector: "cva-header-expand-button", inputs: ["expandHeaderButton", "columns", "moduleName"], outputs: ["onChange"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "pipe", type: SecureImgPipe, name: "secure" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaTableComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-table',
                    standalone: false,
                    template: `
    <div class="table-responsive">
      <ng-container *ngIf="!!expandHeaderButton">
        <cva-header-expand-button [moduleName]="moduleName" [expandHeaderButton]="expandHeaderButton"
                                  [columns]="columns" (onChange)="this.onChangeDisplayColumn.emit($event)">
        </cva-header-expand-button>
      </ng-container>
      <table mat-table #table [dataSource]="results" class="mat-elevation-z8 cva-table">
        <ng-container *ngFor="let column of columns" matColumnDef="{{column.columnDef}}">
          <ng-container *matHeaderCellDef>
            <th mat-header-cell [ngClass]="TableService.getColumnHeaderClassName(column)"
                *ngIf="onDisplayHeaderCell(column)"
                [ngSwitch]="TableService.getColumnType(column, null)">
              <div fxLayout="row" *ngSwitchDefault
                   class="viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   [fxLayoutAlign]="column.alignHeader ? column.alignHeader : TableService.alignCellContent(column)">
                {{ TableService.displayHeaderName(column, moduleName) | translate }}
              </div>
              <mat-checkbox *ngSwitchCase="ColumnTypes.CHECKBOX"
                            color="primary" class="box-select-all" [(ngModel)]="selectAllChecked"
                            (change)="toggleSelectAll($event, column)"
                            [fxLayoutAlign]="column.alignHeader ? column.alignHeader : TableService.alignCellContent(column)">
              </mat-checkbox>
            </th>
          </ng-container>
          <ng-container *matCellDef="let result;">
            <td mat-cell [ngClass]="TableService.getColumnClassName(column, result)"
                *ngIf="onDisplayCell(column, result)"
                [ngSwitch]="TableService.getColumnType(column, result)">
              <div title="{{column.title(result)}}" *ngSwitchDefault
                   class="{{TableService.getColumnClassName(column, result)}} viewData"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)">
                {{ column.cell(result) }}
              </div>
              <ng-container *ngSwitchCase="ColumnTypes.BUTTON">
                <div *ngIf="!!column.button"
                     class="{{TableService.getColumnClassName(column, result)}}"
                     fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                     (click)="$event.stopPropagation()">
                  <button mat-icon-button color="{{column.button.color}}"
                          (click)="onClick(column.button.click, result)"
                          disabled="{{column.button.disabled ? column.button.disabled(result) : false}}"
                          matTooltip="{{(column.button.title ? column.button.title : '') | translate}}"
                          class="{{column.button.className}}" [ngSwitch]="TableService.getIconType(column.button)">
                    <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ column.button.icon }}</mat-icon>
                    <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{column.button.icon}}"></i>
                  </button>
                </div>
              </ng-container>
              <div class="link viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.LINK"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <a [routerLink]="[column.link(result)]">{{ column.cell(result) }}</a>
              </div>

              <div class="label-status viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.STYLE_CSS"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <span [style]="column.style(result)">{{ column.cell(result) }}</span>
              </div>

              <div class="img-view viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result) | secure | async" #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div class="img-view viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG_NO_SECURE"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result)" #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div *ngSwitchCase="ColumnTypes.BASE64"
                   class="img-view viewData"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="'data:image/png;base64,'+column.cell(result)"
                     #base64ImgRef
                     (error)="TableService.onErrorImgEvent(base64ImgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <ng-container *ngSwitchCase="ColumnTypes.CHECKBOX">
                <mat-checkbox [(ngModel)]="result[column.columnDef]" color="primary"
                              *ngIf="column.display ? column.display(result) : true"
                              [disabled]="column.disabled ? column.disabled(result) : false"
                              (change)="toggleSelect($event, result, column)"
                              [fxLayoutAlign]="TableService.alignCellContent(column)">
                </mat-checkbox>
              </ng-container>
            </td>
          </ng-container>
        </ng-container>

        <ng-container *ngFor="let button of buttons; let i = index" matColumnDef="{{button.columnDef}}">
          <ng-container *matHeaderCellDef="let header">
            <!--                    [fxFlex]="(isButtonHeader(button) ? headerButtonWidthDefault : getHeaderButtonWidth(i)) + 'px' "-->
            <!--                    [fxFlex]="getHeaderButtonWidth(i) + 'px' "-->
            <th mat-header-cell [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonHeaderCell(buttons, button, header, i) && !!buttonColspan"
                (click)="$event.stopPropagation()"
                [attr.colspan]="buttonColspan"
            >
              <ng-container *ngIf="TableService.getButtonHeader(button) as btnHeader">
                <button mat-icon-button
                        class="{{button.className}}"
                        *ngIf="((btnHeader && btnHeader.display) ? btnHeader.display(header) : false) "
                        [disabled]="((btnHeader && $any(btnHeader).disabled) ? $any(btnHeader).disabled(header) : false) "
                        color="{{$any(btnHeader).color}}"
                        (click)="onClick($any(btnHeader).click, null)"
                        matTooltip="{{((btnHeader && $any(btnHeader).title) ? $any(btnHeader).title : '') | translate}}"
                        [ngSwitch]="TableService.getIconType($any(btnHeader))">
                  <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ $any(btnHeader).icon }}</mat-icon>
                  <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{$any(btnHeader).icon}}"></i>
                </button>
              </ng-container>
              <ng-container *ngIf="TableService.getButtonHeaderString(button) as btnHeader">
                <div title="{{$any(btnHeader) | translate}}"
                     class="viewData"
                     fxLayout="row"
                     fxLayoutAlign="{{button.alignHeader ? button.alignHeader : AlignEnum.LEFT}} center">
                  {{ $any(btnHeader) | translate }}
                </div>
              </ng-container>
            </th>

          </ng-container>
          <ng-container *matCellDef="let cell">
            <!--                     [fxFlex]="headerButtonWidthDefault + 'px'"-->
            <td mat-cell [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonCell(button, cell)"
                (click)="$event.stopPropagation()">
              <button mat-icon-button color="{{button.color}}"
                      (click)="onClick(button.click, cell)"
                      disabled="{{button.disabled ? button.disabled(cell) : false}}"
                      matTooltip="{{(button.title ? button.title : '') | translate}}"
                      class="{{button.className}}" [ngSwitch]="TableService.getIconType(button)">
                <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ button.icon }}</mat-icon>
                <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{button.icon}}"></i>
              </button>
            </td>
          </ng-container>
        </ng-container>


        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let result; columns: displayedColumns; let i = index"
            [ngClass]="result.className"
            (click)="onRowClick(result, i)"></tr>
      </table>
      <div *ngIf="!(loaderService.isLoading | async)">
        <div class="paging"
             *ngIf="hasData()"
             fxLayout fxLayoutAlign="space-between center">
          <mat-paginator style-paginator
                         [showTotalPages]="showTotalPages"
                         [paging]="varPaging"
                         (pagingChangeEvent)="getPage($event)"
                         [length]="varPaging.totalElements"
                         [pageSize]="varPaging.pageSize"
                         [pageSizeOptions]="pageSizeOptions"
                         [pageIndex]="varPaging.pageNumber - 1">
          </mat-paginator>
          <div class="go-to-page"
               fxLayout fxLayoutGap="0.3rem" fxLayoutAlign="start baseline">
            <mat-label>{{ 'common.gotopage' | translate }}</mat-label>
            <cva-counter-input [(ngModel)]="goToPageNumber"
                               (ngModelChange)="onChangeGoToPageNumber($event)"
                               (onEnter)="goToPage()"
                               [max]="getTotalPage() ? getTotalPage() : 1"
                               [min]="1"
                               [isFloatLabel]="false"
                               [errorMessages]="errorMsg"
            ></cva-counter-input>
            <mat-label style="white-space: nowrap">{{ '/' + getTotalPage() }}</mat-label>
            <button mat-flat-button
                    [disabled]="goToPageNumber < 1 || goToPageNumber > getTotalPage()"
                    (click)="goToPage()">{{ 'common.go' | translate }}
            </button>
          </div>
          <h2 *ngIf="!hasData()">{{ 'common.no.records.found' | translate }}</h2>
        </div>
      </div>
    </div>
  `,
                    providers: [
                        { provide: MatPaginatorIntl, useClass: MultiLanguageTablePaginator },
                    ],
                }]
        }], ctorParameters: () => [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [InjectTokenNextSolutionsConfig]
                }] }, { type: i0.ChangeDetectorRef }, { type: LoaderService }], propDecorators: { moduleName: [{
                type: Input
            }], results: [{
                type: Input
            }], columns: [{
                type: Input
            }], buttons: [{
                type: Input
            }], showTotalPages: [{
                type: Input
            }], expandHeaderButton: [{
                type: Input
            }], pagingChange: [{
                type: Output
            }], clickAction: [{
                type: Output
            }], onRowClickAction: [{
                type: Output
            }], onChangeDisplayColumn: [{
                type: Output
            }], paging: [{
                type: Input
            }] } });

class PatternDirective {
    el;
    navigationKeys = [
        'Backspace',
        'Delete',
        'Tab',
        'Escape',
        'Enter',
        'Home',
        'End',
        'ArrowLeft',
        'ArrowRight',
        'Clear',
        'Copy',
        'Paste'
    ];
    set regPattern(reg) {
        if (reg) {
            this.$regPatternString = reg;
            this.$regPattern = new RegExp(reg);
        }
    }
    $regPatternString = '';
    $regPattern = new RegExp('');
    inputElement;
    constructor(el) {
        this.el = el;
        this.inputElement = el.nativeElement;
    }
    // @Output() valueChange = new EventEmitter()
    // @HostListener('input', ['$event']) onInputChange(event: any) {
    //   const initalValue = this.el.nativeElement.value;
    //   const newValue = initalValue.replace(/[^0-9]*/g, '');
    //   this.el.nativeElement.value = newValue;
    //   this.valueChange.emit(newValue);
    //   if ( initalValue !== this.el.nativeElement.value) {
    //     event.stopPropagation();
    //   }
    // }
    onKeyDown(e) {
        if (this.navigationKeys.indexOf(e.key) > -1 || // Allow: navigation keys: backspace, delete, arrows etc.
            (e.key === 'a' && e.ctrlKey === true) || // Allow: Ctrl+A
            (e.key === 'c' && e.ctrlKey === true) || // Allow: Ctrl+C
            (e.key === 'v' && e.ctrlKey === true) || // Allow: Ctrl+V
            (e.key === 'x' && e.ctrlKey === true) || // Allow: Ctrl+X
            (e.key === 'a' && e.metaKey === true) || // Allow: Cmd+A (Mac)
            (e.key === 'c' && e.metaKey === true) || // Allow: Cmd+C (Mac)
            (e.key === 'v' && e.metaKey === true) || // Allow: Cmd+V (Mac)
            (e.key === 'x' && e.metaKey === true) // Allow: Cmd+X (Mac)
        ) {
            // let it happen, don't do anything
            return;
        }
        // Ensure that it is a number and stop the keypress
        // if (
        //   (e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) &&
        //   (e.keyCode < 96 || e.keyCode > 105)
        // ) {
        //   e.preventDefault();
        // }
        if (!e.key.match(this.$regPattern)) {
            e.preventDefault();
            return;
        }
        const current = this.el.nativeElement.value;
        // @ts-ignore
        const next = current ? current.concat(e.key) : e.key;
        // @ts-ignore
        if (!next || !next.replaceAll(',', '').match(this.$regPattern)) {
            e.preventDefault();
        }
    }
    onPaste(event) {
        event.preventDefault();
        let data = '';
        const pastedInput = event.clipboardData?.getData('text/plain'); // get a digit-only string
        if (this.$regPatternString !== null && this.$regPatternString !== undefined && this.$regPatternString !== '') {
            for (let i = 0; pastedInput && i < pastedInput?.length; i++) {
                if (pastedInput[i].match(this.$regPattern)) {
                    data = data.concat(pastedInput[i]);
                }
            }
        }
        else {
            data = pastedInput;
        }
        document.execCommand('insertText', false, data);
    }
    onDrop(event) {
        event.preventDefault();
        const textData = event.dataTransfer?.getData('text').replace(/\D/g, '');
        this.inputElement.focus();
        document.execCommand('insertText', false, textData);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PatternDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: PatternDirective, isStandalone: false, selector: "[pattern-directive]", inputs: { regPattern: "regPattern" }, host: { listeners: { "keydown": "onKeyDown($event)", "paste": "onPaste($event)", "drop": "onDrop($event)" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PatternDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[pattern-directive]',
                    standalone: false,
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { regPattern: [{
                type: Input,
                args: ['regPattern']
            }], onKeyDown: [{
                type: HostListener,
                args: ['keydown', ['$event']]
            }], onPaste: [{
                type: HostListener,
                args: ['paste', ['$event']]
            }], onDrop: [{
                type: HostListener,
                args: ['drop', ['$event']]
            }] } });

class FormatInputDirective {
    element;
    elementInput;
    control;
    inputDirective;
    constructor(element) {
        this.element = element;
    }
    _value = '';
    get value() {
        return this._value;
    }
    set value(value) {
        this._value = value;
        this.format(value);
    }
    input(value) {
        // If decimal separator is last character don't update
        // because it will delete . || ,
        /*
                if (this.isLastCharacterDecimalSeparator(value)) {
                    this._value = value;
                } else {
                    this._value = this.unformatValue(value)
                }
        */
        // here to notify Angular Validators
        this._onChange(value);
        //        this.format(this._value);
    }
    focusout(value) {
        // If decimal separator is last character don't update
        // because it will delete . || ,
        if (this.isLastCharacterDecimalSeparator(value)) {
            this._value = value;
        }
        else {
            this._value = this.unformatValue(value);
        }
        // here to notify Angular Validators
        this._onChange(this._value);
        this.format(this._value);
    }
    /*
        @HostListener('blur')
        _onBlur() {
            /!**
             * Adding thousand separators
             *!/
            this.format(this._value);
        }
    */
    _onChange(value) {
    }
    /**
     * @param value
     * apply formatting on value assignment
     */
    writeValue(value) {
        this._value = value;
        this.format(this._value);
    }
    registerOnChange(fn) {
        this._onChange = fn;
    }
    registerOnTouched() {
    }
    isLastCharacterDecimalSeparator(value) {
        return isNaN(value[value.length - 1]);
    }
    format(value) {
        if (value === null) {
            this.element.nativeElement.value = '';
            return;
        }
        if (this.isLastCharacterDecimalSeparator(value) && this.elementInput) {
            this.element.nativeElement.value = value;
            return;
        }
        if (this.inputDirective && this.inputDirective.formatValue) {
            const tmp = this.inputDirective.formatValue(value);
            value = tmp === null || tmp === undefined ? value : tmp;
        }
        this.element.nativeElement.value = value ? value : '';
    }
    unformatValue(value) {
        if (this.inputDirective && this.inputDirective.unformatValue) {
            value = this.inputDirective.unformatValue(value);
        }
        return value;
    }
    formatValue(value) {
        return value;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: FormatInputDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: FormatInputDirective, isStandalone: false, selector: "[inputDirective]", inputs: { inputDirective: "inputDirective", value: "value" }, host: { listeners: { "input": "input($event.target.value)", "focusout": "focusout($event.target.value)" } }, providers: [
            { provide: MAT_INPUT_VALUE_ACCESSOR, useExisting: FormatInputDirective },
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => FormatInputDirective),
                multi: true
            }
        ], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: FormatInputDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[inputDirective]',
                    standalone: false,
                    providers: [
                        { provide: MAT_INPUT_VALUE_ACCESSOR, useExisting: FormatInputDirective },
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => FormatInputDirective),
                            multi: true
                        }
                    ]
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { inputDirective: [{
                type: Input,
                args: ['inputDirective']
            }], value: [{
                type: Input,
                args: ['value']
            }], input: [{
                type: HostListener,
                args: ['input', ['$event.target.value']]
            }], focusout: [{
                type: HostListener,
                args: ['focusout', ['$event.target.value']]
            }] } });

class CvaInputComponent {
    injector;
    label = '';
    name = '';
    placeholder = '';
    hint = '';
    required = false;
    disabled = false;
    text = '';
    type = 'text';
    pattern = null;
    readonly = false;
    errorMessages = new Map();
    onChange = new EventEmitter();
    multiline = false;
    isLabelOutside = false;
    isFloatLabel = true;
    minLength;
    maxLength;
    onFocusStatus = false;
    /* hiển thị suffix thay maxlength */
    maxLengthDisplay;
    /* percent label outside css */
    percentOfLabelOutside = 25;
    suffixFontAwesomeClass = '';
    patternFilter = '';
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    formatFunc;
    control = undefined;
    get NsValidator() {
        return ValidatorService;
    }
    constructor(injector, ngControl) {
        this.injector = injector;
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    // Vì không thể quất được NgControl ở constructor nên phải quất ở đây :(
    ngAfterViewInit() {
        //     const ngControl = this.injector.get(NgControl);
        //     if (ngControl) {
        //         this.control = ngControl.control;
        //         this.callValidator();
        //     }
    }
    ngOnInit() {
        this.callValidator();
    }
    get textValue() {
        return this.text;
    }
    set textValue(val) {
        this.writeValue(val);
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.control) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.control = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.control = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.control) {
                if (this.control.validator) {
                    this.control.setValidators([...ValidatorService.generateNsInputValidators({
                            required: this.required,
                            minLength: this.minLength,
                            maxLength: this.maxLength,
                            pattern: this.pattern,
                        }), this.control.validator]);
                }
                else {
                    this.control.setValidators([...ValidatorService.generateNsInputValidators({
                            required: this.required,
                            minLength: this.minLength,
                            maxLength: this.maxLength,
                            pattern: this.pattern,
                        })]);
                }
            }
        }
        if (this.control) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.control.setValue(this.text);
            }
            // Nếu là parent FormControl rồi thì kệ
            this.control.updateValueAndValidity();
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    /**
     * Write a new value to the element.
     */
    writeValue(obj) {
        this.text = obj;
        this.propagateChange(this.text);
        this.callValidator();
        this.onChange.emit(this.text);
    }
    /**
     * Set the function to be called
     * when the formControl receives a change event.
     */
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    /**
     * Set the function to be called
     * when the formControl receives a touch event.
     */
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    displayLength() {
        if (this.maxLength === null || this.maxLength === undefined) {
            return this.maxLengthDisplay ? this.maxLengthDisplay : '';
        }
        return (this.textValue?.length ? this.textValue.length : 0) + '/' + this.getMaxLength();
    }
    getMaxLength() {
        return this.maxLengthDisplay ? this.maxLengthDisplay : this.maxLength;
    }
    onFocus() {
        this.onFocusStatus = true;
    }
    onBlur() {
        if (this.onFocusStatus) {
            this.onFocusStatus = false;
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaInputComponent, deps: [{ token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaInputComponent, isStandalone: false, selector: "cva-input", inputs: { label: "label", name: "name", placeholder: "placeholder", hint: "hint", required: "required", disabled: "disabled", text: "text", type: "type", pattern: "pattern", readonly: "readonly", errorMessages: "errorMessages", multiline: "multiline", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", minLength: "minLength", maxLength: "maxLength", maxLengthDisplay: "maxLengthDisplay", percentOfLabelOutside: "percentOfLabelOutside", suffixFontAwesomeClass: "suffixFontAwesomeClass", patternFilter: "patternFilter", isFormControl: "isFormControl", formatFunc: "formatFunc" }, outputs: { onChange: "onChange" }, ngImport: i0, template: `
      <!-- css labelOutside trong base.theme-->
      <div class="cva-input"
           [ngClass]="{'labelOutside': !!isLabelOutside,
            'float_label': !!isFloatLabel && !isLabelOutside,
            'text_area': !!this.multiline}"
           fxLayout="row" fxLayout.lt-sm="row wrap">
          <mat-label *ngIf="isLabelOutside" class="label_width"
                     fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
              <div class="label">
                <div>
                  {{(label ? label : placeholder) | translate}}<span class="required-label-outside">{{!!required ? '*' : ''}}</span>
                </div>
              </div>
          </mat-label>
          <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                          [ngClass]="{'cva-input-multiline': multiline}"
                          [hideRequiredMarker]="!isFloatLabel"
                          fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
              <mat-label *ngIf="!isLabelOutside && !!isFloatLabel" [ngClass]="{'cva-input-multiline': multiline}">
                  {{(label ? label : placeholder) | translate}}
              </mat-label>
              <input matInput placeholder="{{placeholder|translate}}" [type]="type" [(ngModel)]="textValue"
                     [pattern]="pattern"
                     minLength="{{minLength ? minLength : 0}}"
                     maxLength="{{maxLength ? maxLength : 524288}}"
                     [required]="required"
                     [disabled]="disabled"
                     readonly="{{readonly}}"
                     [inputDirective]="formatFunc"
                     *ngIf="!multiline"
                     (focus)="onFocus()"
                     (blur)="onBlur()"
                     pattern-directive
                     [regPattern]="patternFilter"
                     autocomplete="off">
              <textarea matInput [(ngModel)]="textValue" placeholder="{{placeholder|translate}}"
                        [pattern]="pattern"
                        minLength="{{minLength ? minLength : 0}}"
                        maxLength="{{maxLength ? maxLength : 524288}}"
                        [required]="required"
                        [disabled]="disabled"
                        readonly="{{readonly}}"
                        (focus)="onFocus()"
                        (blur)="onBlur()"
                        *ngIf="multiline"
                        cdkTextareaAutosize cdkAutosizeMinRows="3"
                        autocomplete="off"></textarea>
              <i *ngIf="!!suffixFontAwesomeClass" class="input-suffix {{suffixFontAwesomeClass}}" matSuffix></i>
              <span *ngIf="onFocusStatus && (!!maxLength || !!maxLengthDisplay)" class="input-suffix"
                    matSuffix>{{displayLength()}}</span>
              <mat-hint align="start" *ngIf="!NsValidator.invalid(control)">{{hint | translate}}</mat-hint>
              <mat-hint style="color: red" align="start" *ngIf="NsValidator.invalid(control)">
                  {{NsValidator.getErrorMessageV1(control, errorMessages).msg | translate: NsValidator.getErrorMessageV1(control, errorMessages).params}}
              </mat-hint>
          </mat-form-field>
      </div>
  `, isInline: true, 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: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: i5$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "directive", type: PatternDirective, selector: "[pattern-directive]", inputs: ["regPattern"] }, { kind: "directive", type: FormatInputDirective, selector: "[inputDirective]", inputs: ["inputDirective", "value"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaInputComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-input',
                    standalone: false,
                    template: `
      <!-- css labelOutside trong base.theme-->
      <div class="cva-input"
           [ngClass]="{'labelOutside': !!isLabelOutside,
            'float_label': !!isFloatLabel && !isLabelOutside,
            'text_area': !!this.multiline}"
           fxLayout="row" fxLayout.lt-sm="row wrap">
          <mat-label *ngIf="isLabelOutside" class="label_width"
                     fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
              <div class="label">
                <div>
                  {{(label ? label : placeholder) | translate}}<span class="required-label-outside">{{!!required ? '*' : ''}}</span>
                </div>
              </div>
          </mat-label>
          <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                          [ngClass]="{'cva-input-multiline': multiline}"
                          [hideRequiredMarker]="!isFloatLabel"
                          fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
              <mat-label *ngIf="!isLabelOutside && !!isFloatLabel" [ngClass]="{'cva-input-multiline': multiline}">
                  {{(label ? label : placeholder) | translate}}
              </mat-label>
              <input matInput placeholder="{{placeholder|translate}}" [type]="type" [(ngModel)]="textValue"
                     [pattern]="pattern"
                     minLength="{{minLength ? minLength : 0}}"
                     maxLength="{{maxLength ? maxLength : 524288}}"
                     [required]="required"
                     [disabled]="disabled"
                     readonly="{{readonly}}"
                     [inputDirective]="formatFunc"
                     *ngIf="!multiline"
                     (focus)="onFocus()"
                     (blur)="onBlur()"
                     pattern-directive
                     [regPattern]="patternFilter"
                     autocomplete="off">
              <textarea matInput [(ngModel)]="textValue" placeholder="{{placeholder|translate}}"
                        [pattern]="pattern"
                        minLength="{{minLength ? minLength : 0}}"
                        maxLength="{{maxLength ? maxLength : 524288}}"
                        [required]="required"
                        [disabled]="disabled"
                        readonly="{{readonly}}"
                        (focus)="onFocus()"
                        (blur)="onBlur()"
                        *ngIf="multiline"
                        cdkTextareaAutosize cdkAutosizeMinRows="3"
                        autocomplete="off"></textarea>
              <i *ngIf="!!suffixFontAwesomeClass" class="input-suffix {{suffixFontAwesomeClass}}" matSuffix></i>
              <span *ngIf="onFocusStatus && (!!maxLength || !!maxLengthDisplay)" class="input-suffix"
                    matSuffix>{{displayLength()}}</span>
              <mat-hint align="start" *ngIf="!NsValidator.invalid(control)">{{hint | translate}}</mat-hint>
              <mat-hint style="color: red" align="start" *ngIf="NsValidator.invalid(control)">
                  {{NsValidator.getErrorMessageV1(control, errorMessages).msg | translate: NsValidator.getErrorMessageV1(control, errorMessages).params}}
              </mat-hint>
          </mat-form-field>
      </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { label: [{
                type: Input
            }], name: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], hint: [{
                type: Input
            }], required: [{
                type: Input
            }], disabled: [{
                type: Input
            }], text: [{
                type: Input
            }], type: [{
                type: Input
            }], pattern: [{
                type: Input
            }], readonly: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], onChange: [{
                type: Output
            }], multiline: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], minLength: [{
                type: Input
            }], maxLength: [{
                type: Input
            }], maxLengthDisplay: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], suffixFontAwesomeClass: [{
                type: Input
            }], patternFilter: [{
                type: Input
            }], isFormControl: [{
                type: Input
            }], formatFunc: [{
                type: Input
            }] } });

class NsDateAdapter extends NativeDateAdapter {
    format(date, displayFormat) {
        let day = date.getDate().toString();
        day = +day < 10 ? '0' + day : day;
        let month = (date.getMonth() + 1).toString();
        month = +month < 10 ? '0' + month : month;
        const year = date.getFullYear();
        if (displayFormat === 'input') {
            return `${day}/${month}/${year}`;
        }
        return `${month}/${year}`;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NsDateAdapter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NsDateAdapter });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NsDateAdapter, decorators: [{
            type: Injectable
        }] });
const APP_DATE_FORMATS = {
    parse: {
        dateInput: { month: 'short', year: 'numeric', day: 'numeric' },
    },
    display: {
        dateInput: 'input',
        monthYearLabel: { year: 'numeric', month: 'numeric' },
        dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
        monthYearA11yLabel: { year: 'numeric', month: 'long' },
    },
};

class DateUtilService {
    datePipe;
    injector;
    config;
    DIS_DATE_TIME_FORMAT_DEFAULT = 'dd/MM/yyyy HH:mm';
    constructor(datePipe, injector) {
        this.datePipe = datePipe;
        this.injector = injector;
        this.config = injector.get(InjectTokenNextSolutionsConfig);
    }
    getDateNow() {
        const now = new Date();
        return new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0);
    }
    addDays(date, days) {
        date.setDate(date.getDate() + days);
        return date;
    }
    convertToStartOfDate(dateString) {
        const currentDate = this.convertToDateIgnoreTimeZone(dateString);
        if (currentDate) {
            return new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), 0, 0, 0);
        }
        return new Date(1900, 1, 1);
    }
    convertDateToStringCurrentGMT(date) {
        return this.datePipe.transform(date, this.config.API_DATE_FORMAT);
    }
    convertDateToStringGMT0(date) {
        return this.datePipe.transform(date, this.config.API_DATE_FORMAT, '-0');
    }
    convertDateToDisplayGMT0(date) {
        return this.datePipe.transform(date, this.config.DIS_DATE_FORMAT, '-0');
    }
    convertDateToDisplayServerTime(date) {
        return this.datePipe.transform(date ? date.replace('Z', '') : '', this.config.DIS_DATE_FORMAT);
    }
    convertDateTimeToDisplay(date) {
        return this.datePipe.transform(date.replace('Z', ''), this.config.DIS_DATE_TIME_FORMAT ? this.config.DIS_DATE_TIME_FORMAT : this.DIS_DATE_TIME_FORMAT_DEFAULT);
    }
    convertToDateIgnoreTimeZone(dateStr) {
        if (dateStr != null) {
            return new Date(dateStr.replace('Z', ''));
        }
        else {
            return null;
        }
    }
    convertStringToDate(date) {
        return date ? new Date(date.replace(' ', 'T')) : new Date(1900, 1, 1);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: DateUtilService, deps: [{ token: i2.DatePipe }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: DateUtilService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: DateUtilService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i2.DatePipe }, { type: i0.Injector }] });

class CvaDatePickerComponent {
    dateServiceUtil;
    injector;
    label = '';
    placeholder = '';
    value;
    disabled = false;
    required = false;
    minDate = new Date(1900, 1, 1);
    maxDate = new Date(9999, 12, 31);
    onChange = new EventEmitter();
    errorMessages = new Map();
    isLabelOutside = false;
    isFloatLabel = true;
    /* percent label outside css */
    percentOfLabelOutside = 25;
    title = null;
    config;
    // Chỉ bằng false khi trong NsSmartTable thôi @@
    isFormControl = true;
    formControl;
    get NsValidator() {
        return ValidatorService;
    }
    constructor(dateServiceUtil, ngControl, injector) {
        this.dateServiceUtil = dateServiceUtil;
        this.injector = injector;
        this.config = injector.get(InjectTokenNextSolutionsConfig);
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    ngOnInit() {
        this.callValidator();
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.formControl) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.formControl = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.formControl = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.formControl) {
                this.formControl.setValidators(ValidatorService.generateNsDatePickerValidators({
                    required: this.required,
                    min: this.getMinDate(),
                    max: this.getMaxDate(),
                }));
            }
        }
        if (this.formControl) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.formControl.setValue(this.value);
            }
            // Nếu là parent FormControl rồi thì kệ
            this.formControl.updateValueAndValidity();
            const errorsObj = {};
            const errors = this.formControl.errors;
            if (errors) {
                Object.keys(errors).forEach(key => {
                    errorsObj[key] = errors[key];
                });
            }
            const minValidation = ValidatorService.customMinDateValidatorControl(this.value, this.getMinDate());
            if (minValidation) {
                Object.keys(minValidation).forEach(key => {
                    errorsObj[key] = minValidation[key];
                });
            }
            const maxValidation = ValidatorService.customMaxDateValidatorControl(this.value, this.getMaxDate());
            if (maxValidation) {
                Object.keys(maxValidation).forEach(key => {
                    errorsObj[key] = maxValidation[key];
                });
            }
            if (Object.keys(errorsObj).length > 0) {
                this.formControl.setErrors(errorsObj);
            }
            else {
                this.formControl.setErrors(null);
            }
            this.formControl.markAllAsTouched();
        }
    }
    checkRequired(isRequired) {
        return isRequired ? typeof (isRequired) === 'boolean' ? isRequired : isRequired() : false;
    }
    get datepickerValue() {
        if (this.value instanceof Date) {
            return this.value;
        }
        if (this.isString(this.value) && this.value.indexOf('Z') >= 0) {
            return this.value.replace(' ', 'T');
        }
        return null;
    }
    set datepickerValue(val) {
        this.writeValue(val);
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched(fn) {
        /*NON-EMPTY FOR COMPILE*/
    }
    writeValue(obj) {
        let out = '';
        this.value = obj;
        if (obj) {
            // Nếu là dạng server trả về là string và có Z thì thuộc GMT+0 nên sẽ ép về zone -0
            if (this.isString(this.value) && this.value.indexOf('Z') >= 0) {
                out = this.dateServiceUtil.convertDateToStringGMT0(obj);
            }
            else {
                out = this.dateServiceUtil.convertDateToStringCurrentGMT(this.value);
            }
        }
        if (out) {
            this.title = this.dateServiceUtil.convertDateToDisplayGMT0(out);
        }
        this.propagateChange(out);
        this.callValidator();
        this.onChange.emit(out ? out : '');
    }
    onClear() {
        this.writeValue(null);
    }
    getMinDate() {
        if (this.minDate) {
            return this.minDate instanceof Date ? this.minDate : this.minDate();
        }
        return new Date(1900, 1, 1);
    }
    getMaxDate() {
        if (this.maxDate) {
            return this.maxDate instanceof Date ? this.maxDate : this.maxDate();
        }
        return new Date(9999, 12, 31);
    }
    isString(inputValue) {
        return typeof inputValue === 'string' || inputValue instanceof String;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaDatePickerComponent, deps: [{ token: DateUtilService }, { token: i1$2.NgControl, optional: true, self: true }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaDatePickerComponent, isStandalone: false, selector: "cva-date-picker", inputs: { label: "label", placeholder: "placeholder", value: "value", disabled: "disabled", required: "required", minDate: "minDate", maxDate: "maxDate", errorMessages: "errorMessages", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", percentOfLabelOutside: "percentOfLabelOutside", isFormControl: "isFormControl" }, outputs: { onChange: "onChange" }, providers: [
            { provide: DateAdapter, useClass: NsDateAdapter },
            {
                provide: MAT_DATE_FORMATS,
                useValue: APP_DATE_FORMATS,
            },
        ], ngImport: i0, template: `
    <!-- css labelOutside trong base.theme-->
    <div class="cva-date-picker"
         [ngClass]="{'labelOutside': isLabelOutside, 'float_label': isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && isFloatLabel">{{ (label ? label : placeholder) | translate }}</mat-label>
        <input matInput [matDatepicker]="xDatepicker"
               [placeholder]="placeholder|translate"
               [(ngModel)]="datepickerValue"
               [readonly]="true"
               [required]="checkRequired(required)"
               [title]="title ? title : ''"
               [min]="getMinDate()" [max]="getMaxDate()">
        <mat-datepicker-toggle matPrefix [for]="xDatepicker" [disabled]="disabled"></mat-datepicker-toggle>
        <mat-datepicker #xDatepicker></mat-datepicker>
        <button mat-icon-button color="warn" class="btnDatePicker" matSuffix (click)="onClear()"
                [disabled]="disabled || checkRequired(required)">
          <mat-icon>clear</mat-icon>
        </button>

        <mat-hint style="color: red" *ngIf="NsValidator.invalid(formControl)">
          {{ NsValidator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>

      </mat-form-field>
    </div>
  `, isInline: true, 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: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5$2.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i5$2.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i5$2.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaDatePickerComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-date-picker',
                    standalone: false,
                    template: `
    <!-- css labelOutside trong base.theme-->
    <div class="cva-date-picker"
         [ngClass]="{'labelOutside': isLabelOutside, 'float_label': isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && isFloatLabel">{{ (label ? label : placeholder) | translate }}</mat-label>
        <input matInput [matDatepicker]="xDatepicker"
               [placeholder]="placeholder|translate"
               [(ngModel)]="datepickerValue"
               [readonly]="true"
               [required]="checkRequired(required)"
               [title]="title ? title : ''"
               [min]="getMinDate()" [max]="getMaxDate()">
        <mat-datepicker-toggle matPrefix [for]="xDatepicker" [disabled]="disabled"></mat-datepicker-toggle>
        <mat-datepicker #xDatepicker></mat-datepicker>
        <button mat-icon-button color="warn" class="btnDatePicker" matSuffix (click)="onClear()"
                [disabled]="disabled || checkRequired(required)">
          <mat-icon>clear</mat-icon>
        </button>

        <mat-hint style="color: red" *ngIf="NsValidator.invalid(formControl)">
          {{ NsValidator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>

      </mat-form-field>
    </div>
  `,
                    providers: [
                        { provide: DateAdapter, useClass: NsDateAdapter },
                        {
                            provide: MAT_DATE_FORMATS,
                            useValue: APP_DATE_FORMATS,
                        },
                    ],
                }]
        }], ctorParameters: () => [{ type: DateUtilService }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }, { type: i0.Injector }], propDecorators: { label: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], value: [{
                type: Input
            }], disabled: [{
                type: Input
            }], required: [{
                type: Input
            }], minDate: [{
                type: Input
            }], maxDate: [{
                type: Input
            }], onChange: [{
                type: Output
            }], errorMessages: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], isFormControl: [{
                type: Input
            }] } });

class CvaMultiSelectAutocomplete {
    translateService;
    injector;
    placeholder = '';
    label = '';
    hint = '';
    value = [];
    options = [];
    disabled = false;
    errorMessages = new Map();
    multiple = true;
    required = false;
    isTree = false;
    treeSymbol = ' >> ';
    sizeOfItemsInListByPixels = 39;
    isLabelOutside = false;
    isFloatLabel = true;
    /* percent label outside css */
    percentOfLabelOutside = 25;
    selectionChange = new EventEmitter();
    selectedOptionDataChange = new EventEmitter();
    valueOptionRef = [];
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    searchInputRef;
    // Cái này là để gắn khi nó là FormControl trong 1 FormGroup
    formControl;
    filteredOptions = [];
    selectAllChecked = false;
    labelCount = 1;
    cdkVirtualScrollViewPort;
    constructor(translateService, injector, ngControl) {
        this.translateService = translateService;
        this.injector = injector;
        if (ngControl) {
            ngControl.valueAccessor = this;
        }
    }
    _displayString = '';
    get displayString() {
        return this._displayString;
    }
    get NsValidator() {
        return ValidatorService;
    }
    get selectedValue() {
        return this.value;
    }
    set selectedValue(val) {
        // this.writeValue(val); // Đọc comment bên dưới matSelectionChange
    }
    ngOnInit() {
        this.callValidator();
    }
    getRequired() {
        return typeof this.required === 'function' ? this.required() : this.required;
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        if (ngControl && !this.formControl) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.formControl = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.formControl = new FormControl();
            }
            if (this.formControl) {
                this.formControl.setValidators(ValidatorService.generateNsMultiSelectValidators({
                    required: this.required,
                    multiple: this.multiple,
                }));
            }
        }
        if (this.formControl) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.formControl.setValue(this.value);
            }
            this.formControl.updateValueAndValidity();
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    writeValue(obj) {
        if (obj != null && obj != undefined && this.value !== obj) {
            this.value = obj;
            this.updateSelectAll();
            // this.formControl.setValue(this.value);
            this.propagateChange(this.value);
            this.callValidator();
            this.selectionChange.emit(this.value);
        }
        if (obj != null && obj != undefined && !((this.multiple && this.value.length === this.valueOptionRef.length)
            || (!this.multiple && this.valueOptionRef[0] && this.value === this.valueOptionRef[0].value))) {
            if (this.multiple) {
                this.valueOptionRef = this.options.filter(option => this.value.includes(option.value));
            }
            else {
                this.valueOptionRef = this.options.filter(option => this.value === option.value);
            }
            this.selectedOptionDataChange.emit(this.valueOptionRef);
        }
        this._displayString = this.onDisplayString();
    }
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    ngOnChanges(simpleChanges) {
        if ('options' in simpleChanges) {
            this.options = simpleChanges.options.currentValue;
            this.filteredOptions = this.options;
        }
        if (this.value != null) {
            this.writeValue(this.value);
        }
    }
    toggleSelectAll(val) {
        if (val.checked) {
            let tempChecked = this.value ? this.value : [];
            this.filteredOptions.forEach((option) => {
                if ((!this.value || (this.value && !this.value.includes(option.value))) && !option.disabled) {
                    tempChecked = tempChecked.concat([option.value]);
                }
            });
            this.writeValue(tempChecked);
            this.selectedOptionDataChange.emit(this.filteredOptions.filter((option) => !option.disabled));
        }
        else {
            const filteredValues = [];
            this.filteredOptions.forEach((option) => {
                if (!option.disabled) {
                    filteredValues.push(option.value);
                }
            });
            const filteredSelectedValue = this.value.filter((item) => !filteredValues.includes(item));
            this.writeValue(filteredSelectedValue);
            this.selectedOptionDataChange.emit([]);
        }
        this.selectionChange.emit(this.value);
    }
    filterItem(value) {
        this.filteredOptions = this.options.filter((item) => {
            const translatedDisplayValue = this.translateService.instant(item.displayValue);
            if (translatedDisplayValue) {
                return translatedDisplayValue.toLowerCase().indexOf(value.toLowerCase().trim()) > -1;
            }
            else {
                return item.displayValue.toLowerCase().indexOf(value.toLowerCase().trim()) > -1;
            }
        });
        this.selectAllChecked = !!this.value;
        this.filteredOptions.forEach((item) => {
            if (this.value instanceof Array && !this.value.includes(item.value)) {
                this.selectAllChecked = false;
            }
        });
    }
    onDisplayString() {
        let _displayString = '';
        if (this.value !== null && this.value !== undefined && this.value !== ''
            && (!this.multiple || this.value.length > 0)) {
            let displayOptions = [];
            if (this.multiple) {
                // Multi select display
                for (let i = 0; i < this.labelCount; i++) {
                    displayOptions[i] = this.options.filter(option => option.value === this.value[i])[0];
                }
                if (displayOptions.length) {
                    for (const displayOption of displayOptions) {
                        _displayString += displayOption
                            ? ((this.isTree ? this.onDisplayTreeData(displayOption.displayValue, true) : displayOption.displayValue) + ',')
                            : '';
                    }
                    _displayString = _displayString.slice(0, -1);
                    if (this.value.length > 1) {
                        const strOthers = this.translateService.instant('common.others');
                        _displayString += ` (+${this.value.length - this.labelCount} ${strOthers})`;
                    }
                }
            }
            else {
                // Single select display
                displayOptions = this.options.filter(option => option.value === this.value);
                if (displayOptions.length) {
                    _displayString = this.isTree
                        ? this.onDisplayTreeData(displayOptions[0].displayValue, true)
                        : displayOptions[0].displayValue;
                }
            }
        }
        return _displayString;
    }
    /* Nếu không dùng virtual scroll thì mat-options trong mat-select được load hết
     * Khi toàn bộ mat-options được load hết thì mat-select-trigger sẽ lưu trữ được các giá trị đã chọn
     * Khi chọn 1 hay nhiều thì val.value sẽ là toàn bộ giá trị đã chọn
     */
    /* Khi dùng virtual scroll thì mình chỉ load nhẹ 1 mat-options đầu đã chọn để hack speed displayOptions
     * Khi đó khi chọn lại thì những mat-option không còn trong khung nhìn sẽ bị lỗi tick chọn nên ko dùng hàm này nữa
     */
    matSelectionChange(val) {
        // this.writeValue(val.value);
        // this.emitSelectedData(val);
    }
    onSelectionChange(change) {
        if (!change.isUserInput) {
            return;
        }
        const value = change.source.value;
        if (!this.multiple) {
            this.writeValue(value);
            return;
        }
        const idx = this.value.indexOf(value);
        let tempChecked = this.value ? this.value : [];
        if (idx > -1) {
            tempChecked = tempChecked.filter(x => x !== value);
        }
        else {
            tempChecked = tempChecked.concat([value]);
        }
        this.writeValue(tempChecked);
    }
    updateSelectAll() {
        const filteredValues = [];
        this.filteredOptions.forEach((option) => {
            if (!option.disabled) {
                filteredValues.push(option.value);
            }
        });
        let count = 0;
        if (this.multiple && this.value && this.value instanceof Array && filteredValues) {
            this.value.forEach((item) => {
                count++;
            });
            this.selectAllChecked = count > 0 && count === filteredValues.length;
        }
    }
    onDisplayTreeData(displayValue, isFirstLine) {
        const lastIndex = displayValue.lastIndexOf(this.treeSymbol.trim());
        if (lastIndex < 0) {
            return displayValue;
        }
        if (isFirstLine) {
            return this.translateService.instant(displayValue.substr(lastIndex).replace(this.treeSymbol.trim(), '').trim());
        }
        else {
            const preValue = displayValue.substr(0, lastIndex).trim();
            const preValues = preValue.split(this.treeSymbol.trim());
            let result = '';
            for (const value of preValues) {
                result += this.translateService.instant(value.trim()) + ' ' + this.treeSymbol.trim() + ' ';
            }
            return result ? result.substr(0, result.length - 4) : result;
        }
    }
    openChange($event) {
        if ($event) {
            if (this.cdkVirtualScrollViewPort) {
                this.cdkVirtualScrollViewPort.scrollToIndex(0);
                this.cdkVirtualScrollViewPort.checkViewportSize();
            }
            setTimeout(() => {
                if (this.searchInputRef?.nativeElement) {
                    this.searchInputRef.nativeElement.focus();
                }
            }, 300);
        }
    }
    getItemSize() {
        return this.sizeOfItemsInListByPixels;
    }
    getViewPortHeight() {
        const numberOfItems = this.options.length > 10 ? 10 : this.options.length;
        const height = numberOfItems * this.sizeOfItemsInListByPixels;
        return height > 200 ? 200 : height;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaMultiSelectAutocomplete, deps: [{ token: i1.TranslateService }, { token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaMultiSelectAutocomplete, isStandalone: false, selector: "cva-multi-select-autocomplete", inputs: { placeholder: "placeholder", label: "label", hint: "hint", value: "value", options: "options", disabled: "disabled", errorMessages: "errorMessages", multiple: "multiple", required: "required", isTree: "isTree", treeSymbol: "treeSymbol", sizeOfItemsInListByPixels: "sizeOfItemsInListByPixels", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", percentOfLabelOutside: "percentOfLabelOutside", isFormControl: "isFormControl" }, outputs: { selectionChange: "selectionChange", selectedOptionDataChange: "selectedOptionDataChange" }, viewQueries: [{ propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "cdkVirtualScrollViewPort", first: true, predicate: CdkVirtualScrollViewport, descendants: true }], usesOnChanges: true, ngImport: i0, template: `
    <!-- css labelOutside trong base.theme-->
    <div class="cva-multi-select-autocomplete"
         [ngClass]="{'labelOutside': !!isLabelOutside, 'float_label': !!isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!getRequired() ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label
          *ngIf="!isLabelOutside && !!isFloatLabel">{{ (label ? label : placeholder) | translate }}
        </mat-label>
        <mat-select [disabled]="disabled"
                    [placeholder]="placeholder | translate"
                    [multiple]="multiple"
                    [(ngModel)]="selectedValue"
                    [required]="getRequired()"
                    (selectionChange)="matSelectionChange($event)"
                    (openedChange)="openChange($event)">
          <div class="box-search">
            <mat-checkbox *ngIf="multiple" color="primary" class="box-select-all"
                          [(ngModel)]="selectAllChecked"
                          (change)="toggleSelectAll($event)"></mat-checkbox>
            <input #searchInput type="text" [ngClass]="{'pl-1': !multiple}"
                   (keydown.space)="$event.stopPropagation()"
                   (input)="filterItem(searchInput.value)"
                   placeholder="{{'btnSearch' | translate}}...">
            <div class="box-search-icon" (click)="filterItem(''); searchInput.value = ''">
              <button mat-icon-button class="search-button">
                <mat-icon class="mat-24" aria-label="Search icon">clear</mat-icon>
              </button>
            </div>
          </div>
          <mat-select-trigger title="{{displayString|translate}}">
            {{ displayString | translate }}
          </mat-select-trigger>
          <cdk-virtual-scroll-viewport [itemSize]="getItemSize()"
                                       [style.height.px]="getViewPortHeight()">
            <mat-option *cdkVirtualFor="let option of filteredOptions; let i = index"
                        [attr.data-optionIndex]="i"
                        [disabled]="option.disabled" [value]="option.value"
                        [ngClass]="{'tree-mat-option': isTree}"
                        title="{{option.displayValue|translate}}"
                        (onSelectionChange)="onSelectionChange($event)">
              <div *ngIf="!isTree">{{ option.displayValue | translate }}</div>
              <div *ngIf="!!isTree" class="tree-multiline-mat-option">
                <div mat-line>{{ onDisplayTreeData(option.displayValue, true) }}</div>
                <p mat-line>{{ onDisplayTreeData(option.displayValue, false) }}</p>
              </div>
            </mat-option>
          </cdk-virtual-scroll-viewport>
          <ng-container *ngIf="multiple">
            <ng-container *ngFor="let option of selectedValue; let i = index">
              <mat-option class="selected-options" [value]="option" *ngIf="i===0">
                {{ option }}
              </mat-option>
            </ng-container>
          </ng-container>
          <ng-container *ngIf="!multiple">
            <mat-option class="selected-options" *ngIf="!!selectedValue"
                        [value]="selectedValue">{{ selectedValue }}
            </mat-option>
          </ng-container>
        </mat-select>
        <mat-icon matSuffix>expand_more</mat-icon>
        <mat-hint *ngIf="!NsValidator.invalid(formControl)">{{ hint | translate }}</mat-hint>
        <mat-hint style="color: red" *ngIf="NsValidator.invalid(formControl)">
          {{ NsValidator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </mat-form-field>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i4$2.MatLine, selector: "[mat-line], [matLine]" }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i9$1.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "directive", type: i10.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i10.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i10.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaMultiSelectAutocomplete, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-multi-select-autocomplete',
                    standalone: false,
                    template: `
    <!-- css labelOutside trong base.theme-->
    <div class="cva-multi-select-autocomplete"
         [ngClass]="{'labelOutside': !!isLabelOutside, 'float_label': !!isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!getRequired() ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label
          *ngIf="!isLabelOutside && !!isFloatLabel">{{ (label ? label : placeholder) | translate }}
        </mat-label>
        <mat-select [disabled]="disabled"
                    [placeholder]="placeholder | translate"
                    [multiple]="multiple"
                    [(ngModel)]="selectedValue"
                    [required]="getRequired()"
                    (selectionChange)="matSelectionChange($event)"
                    (openedChange)="openChange($event)">
          <div class="box-search">
            <mat-checkbox *ngIf="multiple" color="primary" class="box-select-all"
                          [(ngModel)]="selectAllChecked"
                          (change)="toggleSelectAll($event)"></mat-checkbox>
            <input #searchInput type="text" [ngClass]="{'pl-1': !multiple}"
                   (keydown.space)="$event.stopPropagation()"
                   (input)="filterItem(searchInput.value)"
                   placeholder="{{'btnSearch' | translate}}...">
            <div class="box-search-icon" (click)="filterItem(''); searchInput.value = ''">
              <button mat-icon-button class="search-button">
                <mat-icon class="mat-24" aria-label="Search icon">clear</mat-icon>
              </button>
            </div>
          </div>
          <mat-select-trigger title="{{displayString|translate}}">
            {{ displayString | translate }}
          </mat-select-trigger>
          <cdk-virtual-scroll-viewport [itemSize]="getItemSize()"
                                       [style.height.px]="getViewPortHeight()">
            <mat-option *cdkVirtualFor="let option of filteredOptions; let i = index"
                        [attr.data-optionIndex]="i"
                        [disabled]="option.disabled" [value]="option.value"
                        [ngClass]="{'tree-mat-option': isTree}"
                        title="{{option.displayValue|translate}}"
                        (onSelectionChange)="onSelectionChange($event)">
              <div *ngIf="!isTree">{{ option.displayValue | translate }}</div>
              <div *ngIf="!!isTree" class="tree-multiline-mat-option">
                <div mat-line>{{ onDisplayTreeData(option.displayValue, true) }}</div>
                <p mat-line>{{ onDisplayTreeData(option.displayValue, false) }}</p>
              </div>
            </mat-option>
          </cdk-virtual-scroll-viewport>
          <ng-container *ngIf="multiple">
            <ng-container *ngFor="let option of selectedValue; let i = index">
              <mat-option class="selected-options" [value]="option" *ngIf="i===0">
                {{ option }}
              </mat-option>
            </ng-container>
          </ng-container>
          <ng-container *ngIf="!multiple">
            <mat-option class="selected-options" *ngIf="!!selectedValue"
                        [value]="selectedValue">{{ selectedValue }}
            </mat-option>
          </ng-container>
        </mat-select>
        <mat-icon matSuffix>expand_more</mat-icon>
        <mat-hint *ngIf="!NsValidator.invalid(formControl)">{{ hint | translate }}</mat-hint>
        <mat-hint style="color: red" *ngIf="NsValidator.invalid(formControl)">
          {{ NsValidator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </mat-form-field>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { placeholder: [{
                type: Input
            }], label: [{
                type: Input
            }], hint: [{
                type: Input
            }], value: [{
                type: Input
            }], options: [{
                type: Input
            }], disabled: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], multiple: [{
                type: Input
            }], required: [{
                type: Input
            }], isTree: [{
                type: Input
            }], treeSymbol: [{
                type: Input
            }], sizeOfItemsInListByPixels: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], selectionChange: [{
                type: Output
            }], selectedOptionDataChange: [{
                type: Output
            }], isFormControl: [{
                type: Input
            }], searchInputRef: [{
                type: ViewChild,
                args: ['searchInput']
            }], cdkVirtualScrollViewPort: [{
                type: ViewChild,
                args: [CdkVirtualScrollViewport, { static: false }]
            }] } });

class CvaLiveSearchingComponent {
    injector;
    label = '';
    placeholder = '';
    hint = '';
    required = false;
    disabled = false;
    readonly = false;
    errorMessages = new Map();
    isLabelOutside = false;
    isFloatLabel = true;
    percentOfLabelOutside = 25;
    suffixFontAwesomeClass = '';
    displayKey = '';
    mappingConfig = {};
    searchFn;
    onChange = new EventEmitter();
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    row;
    columnDef;
    control = undefined;
    textControl = new FormControl('');
    filteredOptions = [];
    selected;
    loading = false;
    searchSub;
    constructor(injector, ngControl) {
        this.injector = injector;
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    get NsValidator() {
        return ValidatorService;
    }
    ngOnInit() {
        this.callValidator();
        this.textValueChangeSubscribe();
        if (!this.isFormControl && !!this.searchFn && this.row && this.columnDef) {
            this.writeValue(this.row[this.columnDef]);
        }
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.control) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.control = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.control = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.control) {
                if (this.control.validator) {
                    this.control.setValidators([...ValidatorService.generateNsAutocompleteValidators({
                            required: this.required,
                        }), this.control.validator]);
                }
                else {
                    this.control.setValidators([...ValidatorService.generateNsAutocompleteValidators({
                            required: this.required,
                        })]);
                }
            }
        }
        if (this.control) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.control.setValue(this.selected);
            }
            // Nếu là parent FormControl rồi thì kệ
            this.control.updateValueAndValidity();
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    /**
     * Set the function to be called
     * when the formControl receives a change event.
     */
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    /**
     * Set the function to be called
     * when the formControl receives a touch event.
     */
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    /**
     * Write a new value to the element.
     */
    writeValue(obj) {
        if (!obj || typeof obj !== 'string') {
            this.selected = {};
            this.filteredOptions.length = 0;
            this.filteredOptions = [];
            this.textControl.setValue('', { emitEvent: false });
            this.updateRowOrFormGroup();
            return;
        }
        const matched = this.filteredOptions.find(opt => {
            return JSON.stringify(opt[this.displayKey] ?? '') === JSON.stringify(obj ?? '');
        });
        if (!matched) {
            if (!this.searchFn) {
                return;
            }
            // Khi textValueChange chưa chạy không tìm thấy
            this.searchFn(obj).subscribe(values => {
                if (values && values.length > 0) {
                    this.filteredOptions = [...values];
                    this.onOptionSelect(obj);
                }
            });
            return;
        }
        this.selected = matched;
        this.textControl.setValue(matched[this.displayKey], { emitEvent: false });
        this.updateRowOrFormGroup();
    }
    onOptionSelect(displayValue) {
        this.searchSub?.unsubscribe();
        this.writeValue(displayValue);
        setTimeout(() => this.textValueChangeSubscribe(), 100);
    }
    textValueChangeSubscribe() {
        this.searchSub = this.textControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), filter(text => typeof text === 'string' && text.trim().length > 0), tap(() => this.loading = true), switchMap((text) => {
            if (typeof text !== 'string' || !text || !text.trim())
                return of([]);
            return this.searchFn ? this.searchFn(text) : of([]);
        }), tap(() => this.loading = false)).subscribe((data) => {
            this.filteredOptions.length = 0;
            this.filteredOptions = [];
            if (!!this.selected && !!this.selected[this.displayKey]) {
                this.filteredOptions.push(this.selected);
                this.filteredOptions.push(...data.filter((x) => x[this.displayKey] !== this.selected[this.displayKey]));
            }
            else {
                this.filteredOptions.push(...data);
            }
        });
    }
    updateRowOrFormGroup() {
        if (!this.isFormControl && this.row) {
            for (const targetKey in this.mappingConfig) {
                const sourceKey = this.mappingConfig[targetKey];
                this.row[targetKey] = this.selected[sourceKey];
            }
        }
        if (this.isFormControl && this.control?.parent) {
            for (const targetKey in this.mappingConfig) {
                const sourceKey = this.mappingConfig[targetKey];
                const formControl = this.control.parent.get(targetKey);
                if (formControl)
                    formControl.setValue(this.selected[sourceKey]);
            }
        }
        this.propagateChange(this.selected[this.displayKey]);
        this.onChange.emit(this.selected[this.displayKey]);
    }
    onClear() {
        this.writeValue(null);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaLiveSearchingComponent, deps: [{ token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaLiveSearchingComponent, isStandalone: false, selector: "cva-live-searching", inputs: { label: "label", placeholder: "placeholder", hint: "hint", required: "required", disabled: "disabled", readonly: "readonly", errorMessages: "errorMessages", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", percentOfLabelOutside: "percentOfLabelOutside", suffixFontAwesomeClass: "suffixFontAwesomeClass", displayKey: "displayKey", mappingConfig: "mappingConfig", searchFn: "searchFn", isFormControl: "isFormControl", row: "row", columnDef: "columnDef" }, outputs: { onChange: "onChange" }, ngImport: i0, template: `
    <div class="cva-live-searching"
         [ngClass]="{'labelOutside': !!isLabelOutside,
            'float_label': !!isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && !!isFloatLabel">
          {{ (label ? label : placeholder) | translate }}
        </mat-label>
        <input type="text"
               matInput
               [required]="required"
               [disabled]="disabled"
               placeholder="{{placeholder|translate}}"
               [formControl]="textControl"
               [matAutocomplete]="auto"
               readonly="{{readonly}}" />
        <button mat-icon-button color="warn" class="btnClear" matSuffix (click)="onClear()" *ngIf="!loading">
          <mat-icon>clear</mat-icon>
        </button>
        <mat-spinner diameter="20" matSuffix *ngIf="loading"></mat-spinner>
        <mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption
                          (optionSelected)="onOptionSelect($event.option.value)">
          <mat-option *ngFor="let option of filteredOptions" [value]="option[displayKey]">
            {{ option[displayKey] }}
          </mat-option>
        </mat-autocomplete>
        <i *ngIf="!!suffixFontAwesomeClass" class="input-suffix {{suffixFontAwesomeClass}}" matSuffix></i>
        <mat-hint align="start" *ngIf="!NsValidator.invalid(control)">{{ hint | translate }}</mat-hint>
        <mat-hint style="color: red" align="start" *ngIf="NsValidator.invalid(control)">
          {{ NsValidator.getErrorMessageV1(control, errorMessages).msg | translate: NsValidator.getErrorMessageV1(control, errorMessages).params }}
        </mat-hint>
      </mat-form-field>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i3$2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i4$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i3$2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i9$2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaLiveSearchingComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-live-searching',
                    standalone: false,
                    template: `
    <div class="cva-live-searching"
         [ngClass]="{'labelOutside': !!isLabelOutside,
            'float_label': !!isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : placeholder) | translate }}<span
            class="required-label-outside">{{ !!required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="!!isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && !!isFloatLabel">
          {{ (label ? label : placeholder) | translate }}
        </mat-label>
        <input type="text"
               matInput
               [required]="required"
               [disabled]="disabled"
               placeholder="{{placeholder|translate}}"
               [formControl]="textControl"
               [matAutocomplete]="auto"
               readonly="{{readonly}}" />
        <button mat-icon-button color="warn" class="btnClear" matSuffix (click)="onClear()" *ngIf="!loading">
          <mat-icon>clear</mat-icon>
        </button>
        <mat-spinner diameter="20" matSuffix *ngIf="loading"></mat-spinner>
        <mat-autocomplete #auto="matAutocomplete" autoActiveFirstOption
                          (optionSelected)="onOptionSelect($event.option.value)">
          <mat-option *ngFor="let option of filteredOptions" [value]="option[displayKey]">
            {{ option[displayKey] }}
          </mat-option>
        </mat-autocomplete>
        <i *ngIf="!!suffixFontAwesomeClass" class="input-suffix {{suffixFontAwesomeClass}}" matSuffix></i>
        <mat-hint align="start" *ngIf="!NsValidator.invalid(control)">{{ hint | translate }}</mat-hint>
        <mat-hint style="color: red" align="start" *ngIf="NsValidator.invalid(control)">
          {{ NsValidator.getErrorMessageV1(control, errorMessages).msg | translate: NsValidator.getErrorMessageV1(control, errorMessages).params }}
        </mat-hint>
      </mat-form-field>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { label: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], hint: [{
                type: Input
            }], required: [{
                type: Input
            }], disabled: [{
                type: Input
            }], readonly: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], suffixFontAwesomeClass: [{
                type: Input
            }], displayKey: [{
                type: Input
            }], mappingConfig: [{
                type: Input
            }], searchFn: [{
                type: Input
            }], onChange: [{
                type: Output
            }], isFormControl: [{
                type: Input
            }], row: [{
                type: Input
            }], columnDef: [{
                type: Input
            }] } });

class CvaSmartTableComponent {
    ref;
    config;
    injector;
    moduleName = '';
    columns = [];
    buttons = [];
    value = [];
    minRow = 0;
    maxRow = 9999;
    errorMessages = new Map();
    isFormControl = true;
    isSticky = false;
    isStickyHeader = false;
    isStickyFooter = false;
    clickAction = new EventEmitter();
    onChange = new EventEmitter();
    matTable;
    isExpandRowTable = false;
    expandRowProperty = '';
    $displayedColumns = [];
    $displayedFooters = [];
    datasource = new MatTableDataSource([]);
    formControl;
    selectAllChecked = false;
    buttonColspan = 0;
    constructor(ref, config, injector, ngControl) {
        this.ref = ref;
        this.config = config;
        this.injector = injector;
        if (ngControl) {
            ngControl.valueAccessor = this;
        }
    }
    get AlignEnum() {
        return AlignEnum;
    }
    get IconTypes() {
        return IconTypeEnum;
    }
    get TableService() {
        return TableService;
    }
    get displayedColumns() {
        if (!this.$displayedColumns || this.$displayedColumns.length <= 0) {
            this.$displayedColumns = this.columns.map((c) => c.columnDef);
            if (this.buttons) {
                this.$displayedColumns = this.$displayedColumns.concat(this.buttons.map((b) => b.columnDef));
            }
        }
        return this.$displayedColumns;
    }
    get displayedFooters() {
        if (!this.$displayedFooters || this.$displayedFooters.length <= 0) {
            for (const column of this.columns) {
                if (!!column.footers) {
                    for (let i = 0; i < column.footers.length; i++) {
                        if (!this.$displayedFooters[i]) {
                            this.$displayedFooters[i] = [];
                        }
                        this.$displayedFooters[i] = this.$displayedFooters[i].concat([i + '-' + column.columnDef]);
                    }
                }
            }
        }
        return this.$displayedFooters;
    }
    get ColumnTypes() {
        return ColumnTypeEnum;
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    writeValue(obj) {
        if (obj) {
            this.value = obj;
            if (this.isExpandRowTable && this.datasource.data !== this.value) {
                this.datasource = new MatTableDataSource(this.value);
                let parentRowIndex = 0;
                for (let i = 0; i < this.datasource.data.length; i++) {
                    const row = this.datasource.data[i];
                    if (!row.isChildRow) {
                        this.expandRow(i, row, parentRowIndex);
                        parentRowIndex = (++parentRowIndex) % 2;
                    }
                }
            }
            else {
                this.datasource = new MatTableDataSource(this.value);
            }
            this.toggleSelect(null);
            this.callValidator();
            this.propagateChange(this.isExpandRowTable ? this.getParentRowData() : this.value);
            this.onChange.emit();
        }
    }
    getParentRowData() {
        return this.value.filter((row) => {
            return !row.isChildRow;
        });
    }
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    ngOnChanges() {
        this.writeValue(this.value);
    }
    ngOnInit() {
        this.callValidator();
    }
    ngAfterContentChecked() {
        this.getHeaderButtonColspan();
        this.ref.detectChanges();
    }
    /*
      Nếu sử dụng expandTableRow khi xử lý sự kiện bên ngoài component không sử dụng index bên trong base, set index lại bằng indexOf
    */
    onClick(action, result, index) {
        const buttonClickEvent = new ButtonClickEvent(action, result, index);
        this.clickAction.emit(buttonClickEvent);
    }
    onCellValueChange(result, column, $event) {
        result[column.columnDef] = $event;
        if (column.onCellValueChange) {
            column.onCellValueChange(result);
        }
        this.callValidator();
        this.onChange.emit();
    }
    toggleSelectAll(val, col) {
        if (this.value) {
            this.value.forEach(v => {
                v.checked = val.checked;
            });
        }
        if (col.onHeaderCellValueChange) {
            col.onHeaderCellValueChange(val.checked);
        }
    }
    toggleSelect(val, result, column) {
        let count = 0;
        if (this.value && this.value.length > 0) {
            this.value.forEach(v => {
                if (v.checked) {
                    count++;
                }
            });
            this.selectAllChecked = count === this.value.length;
        }
        else {
            this.selectAllChecked = false;
        }
        if (column) {
            this.onCellValueChange(result, column, val?.checked);
        }
    }
    onDisplayHeaderCell(column) {
        return column.isShowHeader ? column.isShowHeader : false;
    }
    onDisplayFooter(footer, dataTable) {
        return typeof (footer.display) === 'function' ? footer.display(dataTable) : !!footer.display;
    }
    // //Cái khúc này về sau mà có cái loại validate nào mà ngoài thì mới enable validate cột sau
    // validate(control: AbstractControl): ValidationErrors | null {
    //     let valid = null;
    //
    //     if (this.value) {
    //         for (const row of this.value) {
    //             for (const column of this.columns) {
    //                 if (column.validate) {
    //                     valid = column.validate(row);
    //                     if (valid) {
    //                         break;
    //                     }
    //                 }
    //             }
    //             if (valid) {
    //                 break;
    //             }
    //         }
    //     }
    //     return valid;
    // }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        if (ngControl && !this.formControl) {
            if (this.isFormControl) {
                this.formControl = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.formControl = new FormControl();
            }
            if (this.formControl) {
                this.formControl.setValidators(ValidatorService.generateNsSmartTableValidators({
                    columns: this.columns,
                    minRow: this.minRow,
                    maxRow: this.maxRow,
                }));
            }
        }
        if (this.formControl) {
            if (!this.isFormControl) {
                this.formControl.setValue(this.value);
            }
            this.formControl.updateValueAndValidity();
        }
    }
    getRequired(column) {
        return typeof (column.isRequired) === 'function' ? column.isRequired() : column.isRequired;
    }
    getIsDecimal(column) {
        return column.isDecimal ? typeof (column.isDecimal) === 'boolean' ? column.isDecimal : column.isDecimal() : false;
    }
    getErrorMessageMap(column) {
        return column.errorMessage ? column.errorMessage : new Map();
    }
    expandRow(i, row, parentRowClassIndex) {
        // do not add more rows if the click was on a child row
        if (row.isChildRow) {
            return;
        }
        // default not expand
        // if (row.expanded) {
        //   // remove the flag
        //   row.expanded = false;
        //
        //   // remove the child rows
        //   let childrenDetected = false;
        //   const length = this.datasource.data.length;
        //   for (let index = 0; index < length; index++) {
        //     if (childrenDetected && !this.datasource.data[index].isChildRow) {
        //       break;
        //     }
        //
        //     if (index > i && this.datasource.data[index].isChildRow) {
        //       this.datasource.data.splice(index, 1);
        //       index--;
        //       childrenDetected = true;
        //     }
        //   }
        //
        //   this.matTable?.renderRows();
        //   return;
        // }
        // set expanded to true so we don't expand this row again
        row.expanded = true;
        row.parentRowClassIndex = parentRowClassIndex;
        const itemsToAdd = row[this.expandRowProperty];
        // mark as child rows
        itemsToAdd.forEach(item => {
            item.isChildRow = true;
            item.parentRowClassIndex = parentRowClassIndex;
        });
        // add rows including header row
        itemsToAdd.reverse();
        itemsToAdd.forEach(x => {
            this.datasource.data.splice(i + 1, 0, x);
        });
        // rerender table
        this.matTable?.renderRows();
    }
    getCounterImputAlign(column) {
        return column.align ? column.align : AlignEnum.RIGHT;
    }
    getHeaderButtonColspan() {
        this.buttonColspan = TableService.getHeaderButtonColspan(this.buttons, this.datasource.data);
        return this.buttonColspan;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaSmartTableComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: InjectTokenNextSolutionsConfig }, { token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaSmartTableComponent, isStandalone: false, selector: "cva-smart-table", inputs: { moduleName: "moduleName", columns: "columns", buttons: "buttons", value: "value", minRow: "minRow", maxRow: "maxRow", errorMessages: "errorMessages", isFormControl: "isFormControl", isSticky: "isSticky", isStickyHeader: "isStickyHeader", isStickyFooter: "isStickyFooter", isExpandRowTable: "isExpandRowTable", expandRowProperty: "expandRowProperty" }, outputs: { clickAction: "clickAction", onChange: "onChange" }, viewQueries: [{ propertyName: "matTable", first: true, predicate: ["matTable"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
    <div class="table-responsive"
         [ngClass]="{'fixed_header': isSticky||isStickyHeader, 'fixed_footer': isSticky||isStickyFooter}">
      <table mat-table [dataSource]="datasource" #matTable class="mat-elevation-z8 cva-smart-table">
        <ng-container *ngFor="let column of columns" matColumnDef="{{column.columnDef}}">
          <ng-container *matHeaderCellDef>
            <th mat-header-cell class="{{TableService.getColumnHeaderClassName(column)}}"
                *ngIf="onDisplayHeaderCell(column)">
              <!--                        *ngIf="getColumnType(column, result)!==ColumnTypes.CHECKBOX"-->
              <div [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   fxLayout="row"
                   [fxLayoutAlign]="column.alignHeader ? column.alignHeader : TableService.alignCellContent(column)">
                <mat-checkbox
                  *ngIf="TableService.getColumnType(column, null)===ColumnTypes.CHECKBOX && !column.isNotShowHeaderCheckbox"
                  color="primary" class="box-select-all margin-right-5" [(ngModel)]="selectAllChecked"
                  (change)="toggleSelectAll($event, column)">
                </mat-checkbox>
                {{ TableService.displayHeaderName(column, moduleName) | translate }}<span
                style="color: red">{{ getRequired(column) ? '*' : '' }}</span>
              </div>
            </th>
          </ng-container>
          <ng-container *matCellDef="let result;  let i = index">
            <td mat-cell [ngClass]="TableService.getColumnClassName(column,result)"
                *ngIf="TableService.onDisplayCell(column, result)"
                [ngSwitch]="TableService.getColumnType(column, result)">
              <div title="{{column.title(result)}}"
                   *ngSwitchCase="ColumnTypes.VIEW"
                   class="viewData {{TableService.getColumnClassName(column,result)}}"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)">
                {{ column.cell(result) }}
              </div>
              <div class="link viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.LINK"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <a [routerLink]="[column.link(result)]">{{ column.cell(result) }}</a>
              </div>
              <div class="img-view viewData {{TableService.getColumnClassName(column,result)}}"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result) | secure | async"
                     #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div class="img-view viewData {{TableService.getColumnClassName(column,result)}}"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG_NO_SECURE"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result)"
                     #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div *ngSwitchCase="ColumnTypes.BASE64"
                   class="viewData img-view base64 {{TableService.getColumnClassName(column,result)}}"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="'data:image/png;base64,'+column.cell(result)"
                     #base64ImgRef
                     (error)="TableService.onErrorImgEvent(base64ImgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <ng-container *ngSwitchCase="ColumnTypes.BUTTON">
                <div *ngIf="!!column.button"
                     class="{{TableService.getColumnClassName(column, result)}}"
                     fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                     (click)="$event.stopPropagation()">
                  <button mat-icon-button
                          color="{{column.button.color}}"
                          [ngClass]="column.button.className"
                          (click)="onClick(column.button.click, result, i)"
                          disabled="{{column.button.disabled ? column.button.disabled(result) : false}}"
                          matTooltip="{{(column.button.title ? column.button.title : '') | translate}}"
                          [ngSwitch]="TableService.getIconType(column.button)">
                    <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ column.button.icon }}</mat-icon>
                    <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{column.button.icon}}"></i>
                  </button>
                </div>
              </ng-container>
              <cva-counter-input *ngSwitchCase="ColumnTypes.INPUT_COUNTER"
                                 class="inputNumber" #nsCounterInput
                                 [isFormControl]="false"
                                 [alignNumber]="getCounterImputAlign(column)"
                                 [disabled]="column.disabled ? column.disabled(result) : false"
                                 [value]="result[column.columnDef]"
                                 [required]="getRequired(column)"
                                 [errorMessages]="getErrorMessageMap(column)"
                                 [isDecimal]="getIsDecimal(column)"
                                 [min]="column.min ? column.min(result) : null"
                                 [max]="column.max ? column.max(result) : null"
                                 (onChange)="onCellValueChange(result, column, $event);">
              </cva-counter-input>
              <cva-input *ngSwitchCase="ColumnTypes.INPUT"
                         [isFormControl]="false"
                         [disabled]="column.disabled ? column.disabled(result) : false"
                         [text]="result[column.columnDef]"
                         [minLength]="column.min ? column.min(result) : undefined"
                         [maxLength]="column.max ? column.max(result) : undefined"
                         [required]="getRequired(column)"
                         [errorMessages]="getErrorMessageMap(column)"
                         (onChange)="onCellValueChange(result, column, $event);">
              </cva-input>
              <cva-date-picker *ngSwitchCase="ColumnTypes.DATE_PICKER"
                               [value]="result[column.columnDef]"
                               [isFormControl]="false"
                               [minDate]="column.min ? column.min(result) : null"
                               [maxDate]="column.max ? column.max(result) : null"
                               [required]="getRequired(column)"
                               [disabled]="column.disabled ? column.disabled(result) : false"
                               [errorMessages]="getErrorMessageMap(column)"
                               (onChange)="onCellValueChange(result, column, $event);">
              </cva-date-picker>
              <cva-multi-select-autocomplete [isFormControl]="false"
                                             *ngSwitchCase="ColumnTypes.MULTI_SELECT_AUTOCOMPLETE"
                                             class="multiSelectAutocomplete"
                                             [isTree]="column.isTree"
                                             [value]="result[column.columnDef]"
                                             [errorMessages]="getErrorMessageMap(column)"
                                             [required]="getRequired(column)"
                                             [disabled]="column.disabled ? column.disabled(result) : false"
                                             [multiple]="column.isMultipleSelect"
                                             [options]="column.optionValues(result)"
                                             (selectionChange)="onCellValueChange(result, column, $event);">
              </cva-multi-select-autocomplete>
              <div class="checkbox-cell"
                   fxLayout="row"
                   [fxLayoutAlign]="TableService.alignCellContent(column)"
                   *ngSwitchCase="ColumnTypes.CHECKBOX">
                <mat-checkbox [(ngModel)]="result[column.columnDef]" color="primary"
                              *ngIf="column.display ? column.display(result) : true"
                              [disabled]="column.disabled ? column.disabled(result) : false"
                              (change)="toggleSelect($event,result, column)">
                </mat-checkbox>
              </div>
              <cva-live-searching *ngSwitchCase="ColumnTypes.LIVE_SEARCHING"
                                  [isFormControl]="false" [required]="getRequired(column)"
                                  [row]="result" [columnDef]="column.columnDef"
                                  [searchFn]="column.searchFn"
                                  [mappingConfig]="column.mappingConfig"
                                  [displayKey]="column.displayKey"
                                  [errorMessages]="getErrorMessageMap(column)"
                                  (onChange)="onCellValueChange(result, column, $event)">
              </cva-live-searching>
            </td>
          </ng-container>
        </ng-container>
        <ng-container *ngFor="let button of buttons; let i = index" matColumnDef="{{button.columnDef}}">
          <ng-container *matHeaderCellDef="let header">
            <th mat-header-cell
                [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonHeaderCell(buttons, button, header, i) && !!buttonColspan"
                (click)="$event.stopPropagation()"
                [attr.colspan]="buttonColspan">
              <!--                        [fxFlex]="getHeaderButtonWidth(i) + 'px' "-->
              <ng-container *ngIf="TableService.getButtonHeader(button) as btnHeader">
                <button mat-icon-button
                        class="{{button.className}}"
                        color="{{$any(btnHeader).color}}"
                        (click)="onClick($any(btnHeader).click, null, null)"
                        [disabled]="(btnHeader && $any(btnHeader).disabled) ? $any(btnHeader).disabled(header) : false"
                        *ngIf="(btnHeader && btnHeader.display) ? btnHeader.display(header) : false"
                        matTooltip="{{((btnHeader && $any(btnHeader).title) ? $any(btnHeader).title : '') | translate}}"
                        [ngSwitch]="TableService.getIconType($any(btnHeader))">
                  <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ $any(btnHeader).icon }}</mat-icon>
                  <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{$any(btnHeader).icon}}"></i>
                </button>
              </ng-container>
              <ng-container *ngIf="TableService.getButtonHeaderString(button) as btnHeader">
                <div title="{{$any(btnHeader) | translate}}"
                     class="viewData"
                     fxLayout="row"
                     fxLayoutAlign="{{button.alignHeader ? button.alignHeader : AlignEnum.LEFT}} center">
                  {{ $any(btnHeader) | translate }}
                </div>
              </ng-container>
            </th>
          </ng-container>
          <ng-container *matCellDef="let cell; let i = index">
            <td mat-cell [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonCell(button, cell)"
                (click)="$event.stopPropagation()">
              <button mat-icon-button
                      color="{{button.color}}"
                      [ngClass]="button.className"
                      (click)="onClick(button.click, cell, i)"
                      disabled="{{button.disabled ? button.disabled(cell) : false}}"
                      matTooltip="{{(button.title ? button.title : '') | translate}}"
                      [ngSwitch]="TableService.getIconType(button)">
                <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ button.icon }}</mat-icon>
                <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{button.icon}}"></i>
              </button>
            </td>
          </ng-container>
        </ng-container>
        <ng-container *ngFor="let column of columns">
          <ng-container *ngFor="let footer of column.footers; let i = index"
                        matColumnDef="{{i}}-{{column.columnDef}}">
            <ng-container *matFooterCellDef>
              <td mat-footer-cell *ngIf="onDisplayFooter(footer, datasource.data)"
                  [attr.colspan]="TableService.getColspan(footer, datasource.data)"
                  class="{{TableService.getColumnClassName(column,datasource.data)}} {{TableService.getColumnClassName(column.footer,datasource.data)}}">
                <div title="{{footer.title(datasource.data)}}"
                     class="viewData {{TableService.getColumnClassName(column,datasource.data)}}"
                     fxLayout="row"
                     [fxLayoutAlign]="footer.align ? footer.align : AlignEnum.LEFT">
                  {{ footer.cell(datasource.data) }}
                </div>
              </td>
            </ng-container>
          </ng-container>
        </ng-container>
        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: isSticky||isStickyHeader"></tr>
        <tr mat-row *matRowDef="let result; columns: displayedColumns;" class="{{result.className}}"
            [ngClass]="{'childRow0': !!result.isChildRow && result.parentRowClassIndex === 0,
                                   'parentRow0': !result.isChildRow  && result.parentRowClassIndex === 0,
                                   'childRow1': !!result.isChildRow && result.parentRowClassIndex === 1,
                                   'parentRow1': !result.isChildRow  && result.parentRowClassIndex === 1}"
        ></tr>
        <ng-container *ngFor="let df of displayedFooters">
          <tr mat-footer-row *matFooterRowDef="df; sticky: isSticky||isStickyFooter"></tr>
        </ng-container>
      </table>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i5.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i5.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i5.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i5.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i5.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i5.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i5.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i5.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i5.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i5.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i5.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i5.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i5.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i5.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i8$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "component", type: CvaInputComponent, selector: "cva-input", inputs: ["label", "name", "placeholder", "hint", "required", "disabled", "text", "type", "pattern", "readonly", "errorMessages", "multiline", "isLabelOutside", "isFloatLabel", "minLength", "maxLength", "maxLengthDisplay", "percentOfLabelOutside", "suffixFontAwesomeClass", "patternFilter", "isFormControl", "formatFunc"], outputs: ["onChange"] }, { kind: "component", type: CvaCounterInputComponent, selector: "cva-counter-input", inputs: ["label", "placeholder", "suffixText", "hint", "value", "disabled", "required", "errorMessages", "min", "max", "error", "isDecimal", "isLabelOutside", "isFloatLabel", "percentOfLabelOutside", "alignNumber", "isFormControl"], outputs: ["onChange", "onEnter"] }, { kind: "component", type: CvaDatePickerComponent, selector: "cva-date-picker", inputs: ["label", "placeholder", "value", "disabled", "required", "minDate", "maxDate", "errorMessages", "isLabelOutside", "isFloatLabel", "percentOfLabelOutside", "isFormControl"], outputs: ["onChange"] }, { kind: "component", type: CvaMultiSelectAutocomplete, selector: "cva-multi-select-autocomplete", inputs: ["placeholder", "label", "hint", "value", "options", "disabled", "errorMessages", "multiple", "required", "isTree", "treeSymbol", "sizeOfItemsInListByPixels", "isLabelOutside", "isFloatLabel", "percentOfLabelOutside", "isFormControl"], outputs: ["selectionChange", "selectedOptionDataChange"] }, { kind: "component", type: CvaLiveSearchingComponent, selector: "cva-live-searching", inputs: ["label", "placeholder", "hint", "required", "disabled", "readonly", "errorMessages", "isLabelOutside", "isFloatLabel", "percentOfLabelOutside", "suffixFontAwesomeClass", "displayKey", "mappingConfig", "searchFn", "isFormControl", "row", "columnDef"], outputs: ["onChange"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "pipe", type: SecureImgPipe, name: "secure" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaSmartTableComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-smart-table',
                    standalone: false,
                    template: `
    <div class="table-responsive"
         [ngClass]="{'fixed_header': isSticky||isStickyHeader, 'fixed_footer': isSticky||isStickyFooter}">
      <table mat-table [dataSource]="datasource" #matTable class="mat-elevation-z8 cva-smart-table">
        <ng-container *ngFor="let column of columns" matColumnDef="{{column.columnDef}}">
          <ng-container *matHeaderCellDef>
            <th mat-header-cell class="{{TableService.getColumnHeaderClassName(column)}}"
                *ngIf="onDisplayHeaderCell(column)">
              <!--                        *ngIf="getColumnType(column, result)!==ColumnTypes.CHECKBOX"-->
              <div [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   fxLayout="row"
                   [fxLayoutAlign]="column.alignHeader ? column.alignHeader : TableService.alignCellContent(column)">
                <mat-checkbox
                  *ngIf="TableService.getColumnType(column, null)===ColumnTypes.CHECKBOX && !column.isNotShowHeaderCheckbox"
                  color="primary" class="box-select-all margin-right-5" [(ngModel)]="selectAllChecked"
                  (change)="toggleSelectAll($event, column)">
                </mat-checkbox>
                {{ TableService.displayHeaderName(column, moduleName) | translate }}<span
                style="color: red">{{ getRequired(column) ? '*' : '' }}</span>
              </div>
            </th>
          </ng-container>
          <ng-container *matCellDef="let result;  let i = index">
            <td mat-cell [ngClass]="TableService.getColumnClassName(column,result)"
                *ngIf="TableService.onDisplayCell(column, result)"
                [ngSwitch]="TableService.getColumnType(column, result)">
              <div title="{{column.title(result)}}"
                   *ngSwitchCase="ColumnTypes.VIEW"
                   class="viewData {{TableService.getColumnClassName(column,result)}}"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)">
                {{ column.cell(result) }}
              </div>
              <div class="link viewData"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.LINK"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <a [routerLink]="[column.link(result)]">{{ column.cell(result) }}</a>
              </div>
              <div class="img-view viewData {{TableService.getColumnClassName(column,result)}}"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result) | secure | async"
                     #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div class="img-view viewData {{TableService.getColumnClassName(column,result)}}"
                   [ngClass]="{'break-word-style-view': column.hasWordBreakStyle}"
                   *ngSwitchCase="ColumnTypes.IMG_NO_SECURE"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="column.cell(result)"
                     #imgRef
                     (error)="TableService.onErrorImgEvent(imgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <div *ngSwitchCase="ColumnTypes.BASE64"
                   class="viewData img-view base64 {{TableService.getColumnClassName(column,result)}}"
                   fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                   title="{{column.title(result)}}">
                <img [src]="'data:image/png;base64,'+column.cell(result)"
                     #base64ImgRef
                     (error)="TableService.onErrorImgEvent(base64ImgRef, config.NO_IMAGE_AVAILABLE)" alt="" />
              </div>
              <ng-container *ngSwitchCase="ColumnTypes.BUTTON">
                <div *ngIf="!!column.button"
                     class="{{TableService.getColumnClassName(column, result)}}"
                     fxLayout="row" [fxLayoutAlign]="TableService.alignCellContent(column)"
                     (click)="$event.stopPropagation()">
                  <button mat-icon-button
                          color="{{column.button.color}}"
                          [ngClass]="column.button.className"
                          (click)="onClick(column.button.click, result, i)"
                          disabled="{{column.button.disabled ? column.button.disabled(result) : false}}"
                          matTooltip="{{(column.button.title ? column.button.title : '') | translate}}"
                          [ngSwitch]="TableService.getIconType(column.button)">
                    <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ column.button.icon }}</mat-icon>
                    <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{column.button.icon}}"></i>
                  </button>
                </div>
              </ng-container>
              <cva-counter-input *ngSwitchCase="ColumnTypes.INPUT_COUNTER"
                                 class="inputNumber" #nsCounterInput
                                 [isFormControl]="false"
                                 [alignNumber]="getCounterImputAlign(column)"
                                 [disabled]="column.disabled ? column.disabled(result) : false"
                                 [value]="result[column.columnDef]"
                                 [required]="getRequired(column)"
                                 [errorMessages]="getErrorMessageMap(column)"
                                 [isDecimal]="getIsDecimal(column)"
                                 [min]="column.min ? column.min(result) : null"
                                 [max]="column.max ? column.max(result) : null"
                                 (onChange)="onCellValueChange(result, column, $event);">
              </cva-counter-input>
              <cva-input *ngSwitchCase="ColumnTypes.INPUT"
                         [isFormControl]="false"
                         [disabled]="column.disabled ? column.disabled(result) : false"
                         [text]="result[column.columnDef]"
                         [minLength]="column.min ? column.min(result) : undefined"
                         [maxLength]="column.max ? column.max(result) : undefined"
                         [required]="getRequired(column)"
                         [errorMessages]="getErrorMessageMap(column)"
                         (onChange)="onCellValueChange(result, column, $event);">
              </cva-input>
              <cva-date-picker *ngSwitchCase="ColumnTypes.DATE_PICKER"
                               [value]="result[column.columnDef]"
                               [isFormControl]="false"
                               [minDate]="column.min ? column.min(result) : null"
                               [maxDate]="column.max ? column.max(result) : null"
                               [required]="getRequired(column)"
                               [disabled]="column.disabled ? column.disabled(result) : false"
                               [errorMessages]="getErrorMessageMap(column)"
                               (onChange)="onCellValueChange(result, column, $event);">
              </cva-date-picker>
              <cva-multi-select-autocomplete [isFormControl]="false"
                                             *ngSwitchCase="ColumnTypes.MULTI_SELECT_AUTOCOMPLETE"
                                             class="multiSelectAutocomplete"
                                             [isTree]="column.isTree"
                                             [value]="result[column.columnDef]"
                                             [errorMessages]="getErrorMessageMap(column)"
                                             [required]="getRequired(column)"
                                             [disabled]="column.disabled ? column.disabled(result) : false"
                                             [multiple]="column.isMultipleSelect"
                                             [options]="column.optionValues(result)"
                                             (selectionChange)="onCellValueChange(result, column, $event);">
              </cva-multi-select-autocomplete>
              <div class="checkbox-cell"
                   fxLayout="row"
                   [fxLayoutAlign]="TableService.alignCellContent(column)"
                   *ngSwitchCase="ColumnTypes.CHECKBOX">
                <mat-checkbox [(ngModel)]="result[column.columnDef]" color="primary"
                              *ngIf="column.display ? column.display(result) : true"
                              [disabled]="column.disabled ? column.disabled(result) : false"
                              (change)="toggleSelect($event,result, column)">
                </mat-checkbox>
              </div>
              <cva-live-searching *ngSwitchCase="ColumnTypes.LIVE_SEARCHING"
                                  [isFormControl]="false" [required]="getRequired(column)"
                                  [row]="result" [columnDef]="column.columnDef"
                                  [searchFn]="column.searchFn"
                                  [mappingConfig]="column.mappingConfig"
                                  [displayKey]="column.displayKey"
                                  [errorMessages]="getErrorMessageMap(column)"
                                  (onChange)="onCellValueChange(result, column, $event)">
              </cva-live-searching>
            </td>
          </ng-container>
        </ng-container>
        <ng-container *ngFor="let button of buttons; let i = index" matColumnDef="{{button.columnDef}}">
          <ng-container *matHeaderCellDef="let header">
            <th mat-header-cell
                [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonHeaderCell(buttons, button, header, i) && !!buttonColspan"
                (click)="$event.stopPropagation()"
                [attr.colspan]="buttonColspan">
              <!--                        [fxFlex]="getHeaderButtonWidth(i) + 'px' "-->
              <ng-container *ngIf="TableService.getButtonHeader(button) as btnHeader">
                <button mat-icon-button
                        class="{{button.className}}"
                        color="{{$any(btnHeader).color}}"
                        (click)="onClick($any(btnHeader).click, null, null)"
                        [disabled]="(btnHeader && $any(btnHeader).disabled) ? $any(btnHeader).disabled(header) : false"
                        *ngIf="(btnHeader && btnHeader.display) ? btnHeader.display(header) : false"
                        matTooltip="{{((btnHeader && $any(btnHeader).title) ? $any(btnHeader).title : '') | translate}}"
                        [ngSwitch]="TableService.getIconType($any(btnHeader))">
                  <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ $any(btnHeader).icon }}</mat-icon>
                  <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{$any(btnHeader).icon}}"></i>
                </button>
              </ng-container>
              <ng-container *ngIf="TableService.getButtonHeaderString(button) as btnHeader">
                <div title="{{$any(btnHeader) | translate}}"
                     class="viewData"
                     fxLayout="row"
                     fxLayoutAlign="{{button.alignHeader ? button.alignHeader : AlignEnum.LEFT}} center">
                  {{ $any(btnHeader) | translate }}
                </div>
              </ng-container>
            </th>
          </ng-container>
          <ng-container *matCellDef="let cell; let i = index">
            <td mat-cell [ngClass]="button.className"
                *ngIf="TableService.onDisplayButtonCell(button, cell)"
                (click)="$event.stopPropagation()">
              <button mat-icon-button
                      color="{{button.color}}"
                      [ngClass]="button.className"
                      (click)="onClick(button.click, cell, i)"
                      disabled="{{button.disabled ? button.disabled(cell) : false}}"
                      matTooltip="{{(button.title ? button.title : '') | translate}}"
                      [ngSwitch]="TableService.getIconType(button)">
                <mat-icon *ngSwitchCase="IconTypes.MATERIAL_ICON">{{ button.icon }}</mat-icon>
                <i *ngSwitchCase="IconTypes.FONT_AWESOME" class="{{button.icon}}"></i>
              </button>
            </td>
          </ng-container>
        </ng-container>
        <ng-container *ngFor="let column of columns">
          <ng-container *ngFor="let footer of column.footers; let i = index"
                        matColumnDef="{{i}}-{{column.columnDef}}">
            <ng-container *matFooterCellDef>
              <td mat-footer-cell *ngIf="onDisplayFooter(footer, datasource.data)"
                  [attr.colspan]="TableService.getColspan(footer, datasource.data)"
                  class="{{TableService.getColumnClassName(column,datasource.data)}} {{TableService.getColumnClassName(column.footer,datasource.data)}}">
                <div title="{{footer.title(datasource.data)}}"
                     class="viewData {{TableService.getColumnClassName(column,datasource.data)}}"
                     fxLayout="row"
                     [fxLayoutAlign]="footer.align ? footer.align : AlignEnum.LEFT">
                  {{ footer.cell(datasource.data) }}
                </div>
              </td>
            </ng-container>
          </ng-container>
        </ng-container>
        <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: isSticky||isStickyHeader"></tr>
        <tr mat-row *matRowDef="let result; columns: displayedColumns;" class="{{result.className}}"
            [ngClass]="{'childRow0': !!result.isChildRow && result.parentRowClassIndex === 0,
                                   'parentRow0': !result.isChildRow  && result.parentRowClassIndex === 0,
                                   'childRow1': !!result.isChildRow && result.parentRowClassIndex === 1,
                                   'parentRow1': !result.isChildRow  && result.parentRowClassIndex === 1}"
        ></tr>
        <ng-container *ngFor="let df of displayedFooters">
          <tr mat-footer-row *matFooterRowDef="df; sticky: isSticky||isStickyFooter"></tr>
        </ng-container>
      </table>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [InjectTokenNextSolutionsConfig]
                }] }, { type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { moduleName: [{
                type: Input
            }], columns: [{
                type: Input
            }], buttons: [{
                type: Input
            }], value: [{
                type: Input
            }], minRow: [{
                type: Input
            }], maxRow: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], isFormControl: [{
                type: Input
            }], isSticky: [{
                type: Input
            }], isStickyHeader: [{
                type: Input
            }], isStickyFooter: [{
                type: Input
            }], clickAction: [{
                type: Output
            }], onChange: [{
                type: Output
            }], matTable: [{
                type: ViewChild,
                args: ['matTable']
            }], isExpandRowTable: [{
                type: Input
            }], expandRowProperty: [{
                type: Input
            }] } });

/**
 *  Đây chỉ là control trung gian khi chọn ngày, còn xử lý vẫn xử lý 2 control fromDate và toDate (mặc định)
 *  hoặc được truyền control name chỉ định trong input.
 *  Khi khai báo cần khai báo 2 control name con tương ứng nếu không mặc định 2 control con là fromDate và toDate
 */
class CvaRangeDatePickerComponent {
    dateServiceUtil;
    injector;
    label = 'common.apply.time';
    placeholderFromDate = '';
    placeholderToDate = '';
    /**
     * giá trị là true khi muốn disabled tất cả control
     */
    disabledAll = false;
    /**
     * giá trị là true khi muốn disabled control name fromDate
     */
    disabledFromDate = false;
    value = new RangeDatePickerModel();
    requiredFromDate = false;
    requiredToDate = false;
    minDate = new Date(1900, 1, 1);
    maxDate = new Date(9999, 12, 31);
    onChange = new EventEmitter();
    onOpenPicker = new EventEmitter();
    /** key: requiredFromDate, requiredToDate, min, max */
    errorMessages = new Map();
    isLabelOutside = false;
    isFloatLabel = true;
    /** percent label outside css */
    percentOfLabelOutside = 25;
    fromDateControlName = 'fromDate';
    toDateControlName = 'toDate';
    title = '';
    // config: NiceComponentLibraryConfig;
    // Chỉ bằng false khi trong NsSmartTable thôi @@
    isFormControl = true;
    formControl;
    defaultFromDate; // lưu giá trị khởi tạo ban đầu khi truyền từ bên ngoài vào
    get NsValiator() {
        return ValidatorService;
    }
    constructor(dateServiceUtil, ngControl, injector) {
        this.dateServiceUtil = dateServiceUtil;
        this.injector = injector;
        // this.config = injector.get(InjectTokenNextSolutionsConfig);
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    get fromDateValue() {
        if (this.value.fromDate instanceof Date) {
            return this.value.fromDate;
        }
        if (this.isString(this.value.fromDate) && this.value.fromDate.indexOf('Z') >= 0) {
            return this.value.fromDate.replace(' ', 'T');
        }
        return null;
    }
    set fromDateValue(val) {
        this.value.fromDate = val;
    }
    get toDateValue() {
        if (this.value.toDate instanceof Date) {
            return this.value.toDate;
        }
        if (this.isString(this.value.toDate) && this.value.toDate.indexOf('Z') >= 0) {
            return this.value.toDate.replace(' ', 'T').replace('Z', '');
        }
        return null;
    }
    set toDateValue(val) {
        this.value.toDate = val;
        this.writeValue(this.value);
    }
    ngOnInit() {
        this.callValidator();
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    registerOnChange(fn) {
        this.propagateChange(fn);
    }
    registerOnTouched(fn) {
        this.propagateChange(fn);
    }
    writeValue(obj) {
        if (!obj) {
            obj = new RangeDatePickerModel();
        }
        if (!this.defaultFromDate && this.value.fromDate instanceof Date) {
            this.defaultFromDate = this.prepareWriteValueData(this.value.fromDate);
        }
        // this.value = obj;
        this.value.fromDate = this.prepareWriteValueData(obj.fromDate);
        this.value.toDate = this.prepareWriteValueData(obj.toDate);
        this.createTitle();
        this.propagateChange(this.value);
        this.callValidator();
        this.onChange.emit(this.value);
        if (this.defaultFromDate && this.getDisabled(this.disabledFromDate)) {
            this.value.fromDate = new Date(this.defaultFromDate.replace('Z', ''));
        }
    }
    getDisabled(disabled) {
        return typeof disabled === 'function' ? disabled() : disabled;
    }
    createTitle() {
        const titleFromDate = this.dateServiceUtil.convertDateToDisplayGMT0(this.value.fromDate);
        const titleToDate = this.dateServiceUtil.convertDateToDisplayGMT0(this.value.toDate);
        this.title = (titleFromDate ? titleFromDate : '') + ' - '
            + (titleToDate ? titleToDate : '');
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.formControl) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.formControl = ngControl.control ? ngControl.control : undefined;
                if (this.formControl && !this.formControl.value) {
                    this.formControl.setValue(this.value);
                }
            }
            else {
                this.formControl = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.formControl) {
                // this.formControl.setValidators(NsValidator.generateNsDateRangePickerValidators(
                //   {
                //     requiredFromDate: this.requiredFromDate,
                //     requiredToDate: this.requiredToDate,
                //   }
                // ));
            }
        }
        if (this.formControl) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.formControl.setValue(this.value);
            }
            // Nếu là parent FormControl rồi thì kệ
            if (this.formControl?.parent && this.formControl instanceof FormControl
                && this.formControl?.parent instanceof FormGroup) {
                const fromDateControl = this.formControl.parent.controls[this.fromDateControlName];
                if (fromDateControl) {
                    fromDateControl.setValue(this.value.fromDate);
                }
                const toDateControl = this.formControl.parent.controls[this.toDateControlName];
                if (toDateControl) {
                    toDateControl.setValue(this.value.toDate);
                }
            }
            this.formControl.updateValueAndValidity();
            const errorsObj = {};
            const errors = this.formControl.errors;
            if (errors) {
                Object.keys(errors).forEach(key => {
                    errorsObj[key] = errors[key];
                });
            }
            if (this.checkRequired(this.requiredFromDate)) {
                if (!this.value.fromDate) {
                    errorsObj['requiredFromDate'] = true;
                }
            }
            if (this.checkRequired(this.requiredToDate)) {
                if (!this.value.toDate) {
                    errorsObj['requiredToDate'] = true;
                }
            }
            if (!(this.getDisabled(this.disabledFromDate) || this.getDisabled(this.disabledAll))) {
                const minValidation = ValidatorService.customMinDateValidatorControl(this.value.fromDate, this.getMinDate());
                if (minValidation) {
                    Object.keys(minValidation).forEach(key => {
                        errorsObj[key] = minValidation[key];
                    });
                    this.formControl.markAsDirty();
                }
            }
            const maxValidation = ValidatorService.customMaxDateValidatorControl(this.value.toDate, this.getMaxDate());
            if (maxValidation) {
                Object.keys(maxValidation).forEach(key => {
                    errorsObj[key] = maxValidation[key];
                });
                this.formControl.markAsDirty();
            }
            if (Object.keys(errorsObj).length > 0) {
                this.formControl.setErrors(errorsObj);
            }
            else {
                this.formControl.setErrors(null);
            }
            this.formControl.markAllAsTouched();
        }
    }
    prepareWriteValueData(val) {
        let out = '';
        if (val) {
            if (this.isString(val) && val.toString().indexOf('Z') >= 0) {
                out = this.dateServiceUtil.convertDateToStringGMT0(val);
            }
            else {
                out = this.dateServiceUtil.convertDateToStringCurrentGMT(val);
            }
        }
        return out;
    }
    isString(inputValue) {
        return typeof inputValue === 'string' || inputValue instanceof String;
    }
    getMinDate() {
        if (this.minDate) {
            return this.minDate instanceof Date ? this.minDate : this.minDate();
        }
        return new Date(1900, 1, 1);
    }
    getMaxDate() {
        if (this.getDisabled(this.disabledAll)) {
            return new Date(9999, 12, 31);
        }
        if (this.maxDate) {
            return this.maxDate instanceof Date ? this.maxDate : this.maxDate();
        }
        return new Date(9999, 12, 31);
    }
    checkRequired(isRequired) {
        return isRequired ? typeof (isRequired) === 'boolean' ? isRequired : isRequired() : false;
    }
    clearRange(event) {
        event.stopPropagation();
        if (this.getDisabled(this.disabledFromDate)) {
            this.value.toDate = '';
        }
        else {
            this.value = new RangeDatePickerModel();
        }
        this.writeValue(this.value);
    }
    openPicker(picker) {
        if (this.onOpenPicker) {
            this.onOpenPicker.emit(picker);
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaRangeDatePickerComponent, deps: [{ token: DateUtilService }, { token: i1$2.NgControl, optional: true, self: true }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaRangeDatePickerComponent, isStandalone: false, selector: "cva-range-date-picker", inputs: { label: "label", placeholderFromDate: "placeholderFromDate", placeholderToDate: "placeholderToDate", disabledAll: "disabledAll", disabledFromDate: "disabledFromDate", value: "value", requiredFromDate: "requiredFromDate", requiredToDate: "requiredToDate", minDate: "minDate", maxDate: "maxDate", errorMessages: "errorMessages", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", percentOfLabelOutside: "percentOfLabelOutside", fromDateControlName: "fromDateControlName", toDateControlName: "toDateControlName", isFormControl: "isFormControl" }, outputs: { onChange: "onChange", onOpenPicker: "onOpenPicker" }, providers: [
            { provide: DateAdapter, useClass: NsDateAdapter },
            {
                provide: MAT_DATE_FORMATS,
                useValue: APP_DATE_FORMATS,
            },
        ], ngImport: i0, template: `
    <div class="cva-range-date-picker"
         [ngClass]="{'labelOutside': isLabelOutside, 'float_label': isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : '') | translate }}<span
            class="required-label-outside">{{ !!(requiredFromDate || requiredToDate) ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && isFloatLabel">{{ (label ? label : '') | translate }}</mat-label>
        <mat-date-range-input [min]="getMinDate()"
                              [max]="getMaxDate()"
                              [rangePicker]="picker"
                              [disabled]="getDisabled(disabledAll)"
                              [title]="title">
          <input matStartDate
                 [(ngModel)]="fromDateValue"
                 readonly="readonly"
                 [placeholder]="placeholderFromDate|translate">
          <input matEndDate
                 [(ngModel)]="toDateValue"
                 readOnly="true"
                 [placeholder]="placeholderToDate|translate">
        </mat-date-range-input>

        <mat-datepicker-toggle matPrefix [for]="picker"
                               [disabled]="getDisabled(disabledAll)">
        </mat-datepicker-toggle>
        <button mat-icon-button matSuffix
                color="warn" class="btnDatePicker"
                (click)="clearRange($event)"
                [disabled]="getDisabled(disabledAll) || (checkRequired(requiredFromDate) && checkRequired(requiredToDate))"
        >
          <mat-icon>clear</mat-icon>
        </button>

        <mat-date-range-picker #picker (opened)="openPicker(picker)"></mat-date-range-picker>
        <mat-hint style="color: red" *ngIf="NsValiator.invalid(formControl)">
          {{ NsValiator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </mat-form-field>
    </div>
  `, isInline: true, 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: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5$2.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: i5$2.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { kind: "directive", type: i5$2.MatStartDate, selector: "input[matStartDate]", outputs: ["dateChange", "dateInput"] }, { kind: "directive", type: i5$2.MatEndDate, selector: "input[matEndDate]", outputs: ["dateChange", "dateInput"] }, { kind: "component", type: i5$2.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i6.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i6.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaRangeDatePickerComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-range-date-picker',
                    standalone: false,
                    template: `
    <div class="cva-range-date-picker"
         [ngClass]="{'labelOutside': isLabelOutside, 'float_label': isFloatLabel && !isLabelOutside}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="isLabelOutside" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : '') | translate }}<span
            class="required-label-outside">{{ !!(requiredFromDate || requiredToDate) ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <mat-form-field appearance="outline" [floatLabel]="isFloatLabel ? 'always' : 'auto'"
                      [hideRequiredMarker]="!isFloatLabel"
                      fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-label *ngIf="!isLabelOutside && isFloatLabel">{{ (label ? label : '') | translate }}</mat-label>
        <mat-date-range-input [min]="getMinDate()"
                              [max]="getMaxDate()"
                              [rangePicker]="picker"
                              [disabled]="getDisabled(disabledAll)"
                              [title]="title">
          <input matStartDate
                 [(ngModel)]="fromDateValue"
                 readonly="readonly"
                 [placeholder]="placeholderFromDate|translate">
          <input matEndDate
                 [(ngModel)]="toDateValue"
                 readOnly="true"
                 [placeholder]="placeholderToDate|translate">
        </mat-date-range-input>

        <mat-datepicker-toggle matPrefix [for]="picker"
                               [disabled]="getDisabled(disabledAll)">
        </mat-datepicker-toggle>
        <button mat-icon-button matSuffix
                color="warn" class="btnDatePicker"
                (click)="clearRange($event)"
                [disabled]="getDisabled(disabledAll) || (checkRequired(requiredFromDate) && checkRequired(requiredToDate))"
        >
          <mat-icon>clear</mat-icon>
        </button>

        <mat-date-range-picker #picker (opened)="openPicker(picker)"></mat-date-range-picker>
        <mat-hint style="color: red" *ngIf="NsValiator.invalid(formControl)">
          {{ NsValiator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </mat-form-field>
    </div>
  `,
                    providers: [
                        { provide: DateAdapter, useClass: NsDateAdapter },
                        {
                            provide: MAT_DATE_FORMATS,
                            useValue: APP_DATE_FORMATS,
                        },
                    ],
                }]
        }], ctorParameters: () => [{ type: DateUtilService }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }, { type: i0.Injector }], propDecorators: { label: [{
                type: Input
            }], placeholderFromDate: [{
                type: Input
            }], placeholderToDate: [{
                type: Input
            }], disabledAll: [{
                type: Input
            }], disabledFromDate: [{
                type: Input
            }], value: [{
                type: Input
            }], requiredFromDate: [{
                type: Input
            }], requiredToDate: [{
                type: Input
            }], minDate: [{
                type: Input
            }], maxDate: [{
                type: Input
            }], onChange: [{
                type: Output
            }], onOpenPicker: [{
                type: Output
            }], errorMessages: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], fromDateControlName: [{
                type: Input
            }], toDateControlName: [{
                type: Input
            }], isFormControl: [{
                type: Input
            }] } });

class DragDropDirective {
    onFileDropped = new EventEmitter();
    background = '#f5fcff';
    opacity = '1';
    //Dragover listener
    onDragOver(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        this.background = '#9ecbec';
        this.opacity = '0.8';
    }
    //Dragleave listener
    onDragLeave(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        this.background = '#f5fcff';
        this.opacity = '1';
    }
    //Drop listener
    ondrop(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        this.background = '#f5fcff';
        this.opacity = '1';
        let files = evt?.dataTransfer?.files;
        if (files && files.length > 0) {
            this.onFileDropped.emit(files);
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: DragDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: DragDropDirective, isStandalone: false, selector: "[appDragDrop]", outputs: { onFileDropped: "onFileDropped" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "ondrop($event)" }, properties: { "style.background-color": "this.background", "style.opacity": "this.opacity" } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: DragDropDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[appDragDrop]',
                    standalone: false,
                }]
        }], propDecorators: { onFileDropped: [{
                type: Output
            }], background: [{
                type: HostBinding,
                args: ['style.background-color']
            }], opacity: [{
                type: HostBinding,
                args: ['style.opacity']
            }], onDragOver: [{
                type: HostListener,
                args: ['dragover', ['$event']]
            }], onDragLeave: [{
                type: HostListener,
                args: ['dragleave', ['$event']]
            }], ondrop: [{
                type: HostListener,
                args: ['drop', ['$event']]
            }] } });

class CvaMultiUploadComponent {
    fileUpload;
    files = [];
    multiple = false;
    maxSize = null;
    accept = null;
    label = '';
    required = '';
    disabled = false;
    /* percent label outside css */
    percentOfLabelOutside = 25;
    onFileChange = new EventEmitter();
    sizeError = null;
    typeError = null;
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    writeValue(obj) {
        if (!obj) {
            return;
        }
        if (this.multiple) {
            this.files.push(obj);
        }
        else {
            this.files = [obj];
        }
        this.propagateChange(this.files);
    }
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    onClick() {
        const fileUpload = this.fileUpload?.nativeElement;
        fileUpload.click();
    }
    convertToUploadModel(fileList) {
        this.sizeError = null;
        this.typeError = null;
        if (fileList && fileList[0]) {
            if (!this.validFile(fileList)) {
                return;
            }
            for (let i = 0; i < fileList.length; i++) {
                const file = fileList[i];
                if (this.isContainFileName(file.name)) {
                    continue;
                }
                const reader = new FileReader();
                reader.onload = (event) => {
                    this.writeValue(new UploadModel(file.name, file, event.target.result));
                    if (!this.multiple || i === fileList.length - 1) {
                        this.onFileChange.emit();
                    }
                };
                reader.readAsDataURL(file);
                if (!this.multiple) {
                    break;
                }
            }
        }
    }
    isContainFileName(name) {
        for (const file of this.files) {
            if (file.name === name) {
                return true;
            }
        }
        return false;
    }
    onFileChangeAction(event) {
        const target = event.target;
        if (target && target.files) {
            this.convertToUploadModel(target.files);
        }
    }
    onFileDroppedAction(fileList) {
        this.convertToUploadModel(fileList);
    }
    validFile(fileList) {
        const acceptStr = this.accept ? this.accept.join() : '';
        for (let i = 0; i < fileList.length; i++) {
            const file = fileList[i];
            if (acceptStr.indexOf(file.type) < 0 || !file.type || file.type === '') {
                this.typeError = file.name;
                return false;
            }
            if (this.maxSize && file.size > this.maxSize) {
                this.sizeError = file.name;
                return false;
            }
        }
        return true;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaMultiUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaMultiUploadComponent, isStandalone: false, selector: "cva-multi-upload", inputs: { files: "files", multiple: "multiple", maxSize: "maxSize", accept: "accept", label: "label", required: "required", disabled: "disabled", percentOfLabelOutside: "percentOfLabelOutside" }, outputs: { onFileChange: "onFileChange" }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => CvaMultiUploadComponent),
                multi: true,
            },
        ], viewQueries: [{ propertyName: "fileUpload", first: true, predicate: ["fileUpload"], descendants: true }], ngImport: i0, template: `
    <div class="cva-multi-upload"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="label" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">{{ (label ? label : '') | translate }}<span
          class="required-label-outside">{{ !!required ? '*' : '' }}</span></div>
      </mat-label>
      <div class="uploadArea"
           fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%"
           appDragDrop (onFileDropped)="onFileDroppedAction($event)">
        <input type="file" multiple #fileUpload (change)="onFileChangeAction($event)"
               [disabled]="disabled"
               accept="{{accept ? accept.join() : '*/*'}}">
        <mat-card>
          <mat-card-actions>
            <button mat-button class="upload-button" color="warn" (click)="onClick()">
              <mat-icon>add</mat-icon>
              <span>{{ 'common.upload.file' | translate }}</span>
            </button>
          </mat-card-actions>
          <mat-card-content>
          </mat-card-content>
        </mat-card>
        <mat-error *ngIf="sizeError!==null">{{ sizeError + ' ' + ('common.is.over-size' | translate) }}</mat-error>
        <mat-error *ngIf="typeError!==null">{{ typeError + ' ' + ('common.is.not-accept' | translate) }}</mat-error>
      </div>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "component", type: i3$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3$3.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i3$3.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: DragDropDirective, selector: "[appDragDrop]", outputs: ["onFileDropped"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaMultiUploadComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-multi-upload',
                    standalone: false,
                    template: `
    <div class="cva-multi-upload"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="label" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">{{ (label ? label : '') | translate }}<span
          class="required-label-outside">{{ !!required ? '*' : '' }}</span></div>
      </mat-label>
      <div class="uploadArea"
           fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%"
           appDragDrop (onFileDropped)="onFileDroppedAction($event)">
        <input type="file" multiple #fileUpload (change)="onFileChangeAction($event)"
               [disabled]="disabled"
               accept="{{accept ? accept.join() : '*/*'}}">
        <mat-card>
          <mat-card-actions>
            <button mat-button class="upload-button" color="warn" (click)="onClick()">
              <mat-icon>add</mat-icon>
              <span>{{ 'common.upload.file' | translate }}</span>
            </button>
          </mat-card-actions>
          <mat-card-content>
          </mat-card-content>
        </mat-card>
        <mat-error *ngIf="sizeError!==null">{{ sizeError + ' ' + ('common.is.over-size' | translate) }}</mat-error>
        <mat-error *ngIf="typeError!==null">{{ typeError + ' ' + ('common.is.not-accept' | translate) }}</mat-error>
      </div>
    </div>
  `,
                    providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => CvaMultiUploadComponent),
                            multi: true,
                        },
                    ],
                }]
        }], propDecorators: { fileUpload: [{
                type: ViewChild,
                args: ['fileUpload', { static: false }]
            }], files: [{
                type: Input
            }], multiple: [{
                type: Input
            }], maxSize: [{
                type: Input
            }], accept: [{
                type: Input
            }], label: [{
                type: Input
            }], required: [{
                type: Input
            }], disabled: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], onFileChange: [{
                type: Output
            }] } });

class DeleteFileEventModel {
    ngControl;
    file;
}
class CvaUploadFileComponent {
    http;
    injector;
    fileSaverService;
    ngControl;
    constructor(http, injector, fileSaverService, ngControl) {
        this.http = http;
        this.injector = injector;
        this.fileSaverService = fileSaverService;
        this.ngControl = ngControl;
        if (ngControl) {
            ngControl.valueAccessor = this;
        }
    }
    fileUpload;
    files = [];
    maxSize = null;
    height = null;
    width = null;
    isSquareImg = false;
    isRectangleImg = false;
    accept = null;
    label = '';
    placeholder = '';
    required = false;
    disabled = false;
    /* percent label outside css */
    percentOfLabelOutside = 25;
    onFileChange = new EventEmitter();
    onFileDelete = new EventEmitter();
    sizeError = null;
    widthError = false;
    heightError = false;
    isSquareError = false;
    isRectangleError = false;
    typeError = null;
    fileType = '';
    fileName = '';
    imgRef = null;
    default$;
    set value(value) {
        this.writeValue(value);
    }
    formControl;
    set defaultUrl(fileInfo) {
        this.default$ = fileInfo.url;
        this.fileType = fileInfo.type;
        this.fileName = fileInfo.name;
        if (1 === 1) {
            return;
        }
        const oReq = new XMLHttpRequest();
        oReq.open('GET', fileInfo.url, true);
        oReq.responseType = 'arraybuffer';
        oReq.onload = (event) => {
            const arrayBuffer = oReq.response; // Note: not oReq.responseText
            if (arrayBuffer) {
                // Create a blob from the response
                const blob = new Blob([arrayBuffer]);
                // onload needed since Google Chrome doesn't support addEventListener for FileReader
                const fileReader = new FileReader();
                const file = new File([blob], fileInfo.name, { type: fileInfo.type });
                fileReader.onload = (event) => {
                    this.writeValue(new UploadModel(fileInfo.name, file, event.target.result));
                };
                // Load blob as Data URL
                fileReader.readAsDataURL(file);
            }
        };
        oReq.send(null);
    }
    ngOnInit() {
        this.callValidator();
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        if (ngControl && !this.formControl) {
            if (ngControl) {
                this.formControl = ngControl.control;
            }
            else {
                this.formControl = new FormControl();
            }
        }
        if (this.formControl) {
            if (this.required && !this.files.length) {
                this.formControl.setErrors({ required: true });
            }
            this.formControl.markAllAsTouched();
        }
    }
    isImageType() {
        return this.fileType.startsWith('image');
    }
    getSrcImg() {
        return this.isImageType() ? ((this.files[0]) ? this.files[0].previewValue : this.default$) : '';
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    writeValue(obj) {
        if (!obj) {
            return;
        }
        if (typeof obj === 'string') {
            const obj1 = { name: this.fileName, binary: null, previewValue: obj };
            this.files = [obj1];
        }
        else if (typeof obj === 'object') {
            if (obj.binary === null || obj.binary === undefined) {
                const obj1 = { id: obj.id, name: obj.name, binary: null, previewValue: obj.previewValue };
                this.files = [obj1];
                this.fileName = obj.name;
                this.fileType = obj.type ? obj.type : '';
            }
            else {
                this.fileName = obj.name;
                this.files = [obj];
            }
        }
        this.propagateChange(this.files);
        this.callValidator();
    }
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    onClick() {
        const fileUpload = this.fileUpload?.nativeElement;
        fileUpload.click();
    }
    convertToUploadModel(fileList) {
        this.sizeError = null;
        this.typeError = null;
        if (fileList && fileList[0]) {
            if (!this.validFile(fileList)) {
                return;
            }
            for (let i = 0; i < fileList.length; i++) {
                const file = fileList[i];
                if (this.isContainFileName(file.name)) {
                    continue;
                }
                const reader = new FileReader();
                reader.onload = (event) => {
                    this.writeValue(new UploadModel(file.name, file, event.target.result));
                    this.fileType = file.type;
                    this.onFileChange.emit();
                };
                reader.readAsDataURL(file);
                break;
            }
        }
    }
    isContainFileName(name) {
        for (const file of this.files) {
            if (file.name === name) {
                return true;
            }
        }
        return false;
    }
    onFileChangeAction(event) {
        const target = event.target;
        if (target && target.files) {
            this.convertToUploadModel(target.files);
        }
    }
    onFileDroppedAction(fileList) {
        this.convertToUploadModel(fileList);
    }
    validFile(fileList) {
        const acceptStr = this.accept ? this.accept.join() : '';
        for (let i = 0; i < fileList.length; i++) {
            const file = fileList[i];
            if (acceptStr.indexOf(file.type) < 0 || !file.type || file.type === '') {
                this.typeError = file.name;
                return false;
            }
            if (this.maxSize && file.size > this.maxSize) {
                this.sizeError = file.name;
                return false;
            }
        }
        return true;
    }
    removeFiles(event, control) {
        if (event) {
            event.stopPropagation();
        }
        this.fileName = '';
        this.fileType = '';
        let deleteFile;
        if (this.files && this.files.length > 0) {
            deleteFile = this.files[0];
            this.files.splice(0, 1);
            this.propagateChange(this.files);
        }
        if (this.fileUpload) {
            this.fileUpload.nativeElement.value = '';
        }
        this.onFileDelete.emit({ ngControl: this.ngControl, file: deleteFile });
    }
    onLoad(img, event) {
        if (this.isSquareImg && img.height && img.width &&
            (((img.height / img.width) > 1.1) || ((img.height / img.width) < 1 / 1.1))) {
            this.removeFiles(undefined);
            this.isSquareError = true;
            return;
        }
        else {
            this.isSquareError = false;
        }
        if (this.isRectangleImg && img.height && img.width &&
            (((img.width / img.height) > 2.2) || ((img.width / img.height) < 2))) {
            this.removeFiles(undefined);
            this.isRectangleError = true;
            return;
        }
        else {
            this.isRectangleError = false;
        }
        if (this.width && img.width !== this.width) {
            this.removeFiles(undefined);
            this.widthError = true;
            return;
        }
        else {
            this.widthError = false;
        }
        if (this.height && img.height !== this.height) {
            this.removeFiles(undefined);
            this.heightError = true;
            return;
        }
        else {
            this.heightError = false;
        }
        const parentElement = img.closest('.preview-image');
        parentElement.setAttribute('style', 'background-image:url("' + img.src + '")');
    }
    previewFiles(event, downloadId) {
        event.stopPropagation();
        downloadId.click();
    }
    downloadFile() {
        const file = this.files[0];
        if (!file) {
            return;
        }
        if (file.id) {
            // copy apiService.saveFile()
            this.http.post(file.previewValue + '', null, {
                headers: undefined,
                params: undefined,
                observe: 'response',
                responseType: 'blob',
            }).subscribe((l) => {
                let filename = '';
                const disposition = l.headers.get('Content-Disposition');
                if (disposition && disposition.indexOf('attachment') !== -1) {
                    const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                    const matches = filenameRegex.exec(disposition);
                    if (matches != null && matches[1]) {
                        filename = matches[1].replace(/['"]/g, '');
                    }
                }
                const blobData = l.body;
                const contentType = l.headers.get('Content-Type');
                if (blobData && contentType) {
                    this.fileSaverService.save(blobData, filename, contentType);
                }
            });
        }
        else {
            if (file.binary) {
                this.fileSaverService.save(file.binary, file.name);
            }
        }
    }
    getRequiredErr() {
        return !this.files.length && this.required && !this.heightError && !this.widthError && !this.isSquareError
            && !this.isRectangleError && !this.typeError && !this.sizeError;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaUploadFileComponent, deps: [{ token: i1$3.HttpClient }, { token: i0.Injector }, { token: i2$1.FileSaverService }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaUploadFileComponent, isStandalone: false, selector: "cva-upload-file", inputs: { files: "files", maxSize: "maxSize", height: "height", width: "width", isSquareImg: "isSquareImg", isRectangleImg: "isRectangleImg", accept: "accept", label: "label", placeholder: "placeholder", required: "required", disabled: "disabled", percentOfLabelOutside: "percentOfLabelOutside", value: "value", defaultUrl: "defaultUrl" }, outputs: { onFileChange: "onFileChange", onFileDelete: "onFileDelete" }, viewQueries: [{ propertyName: "fileUpload", first: true, predicate: ["fileUpload"], descendants: true }], ngImport: i0, template: `
        <div class="cva-multi-upload labelOutside"
             fxLayout="row" fxLayout.lt-sm="row wrap">
            <mat-label *ngIf="label" class="label_width"
                       fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
                <div class="label">{{ (label ? label : '') | translate }}<span
                  class="required-label-outside">{{ !!required ? '*' : '' }}</span></div>
            </mat-label>
            <div class="uploadArea" style="background-color: #FFFFFF"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%"
                 appDragDrop (onFileDropped)="onFileDroppedAction($event)">
                <input type="file" #fileUpload (change)="onFileChangeAction($event)"
                       [disabled]="disabled"
                       accept="{{accept ? accept.join() : '*/*'}}">
                <mat-card>
                    <mat-card-actions>
                        <div fxLayout="column">
                            <button mat-button
                                    class="{{(isImageType() && files[0])?'upload-button preview': 'upload-button'}}"
                                    color="warn" (click)="onClick()">
                                <div class="preview-image"
                                     *ngIf="isImageType() && files[0]">
                                    <img (load)="onLoad(img, $event)"
                                         #img
                                         style="display: none"
                                         [src]="getSrcImg()| secure | async"
                                         *ngIf="isImageType() && files[0]"
                                    />
                                </div>
                                <i [ngClass]="files[0]?'fa fa-file-alt':'fa fa-plus'"
                                   *ngIf="!isImageType()  || !files[0]"></i>
                                <span
                                  *ngIf="!files[0]">{{ ((placeholder ? placeholder : 'common.button.import.file')| translate) }}</span>
                                <i *ngIf="!!files[0]?.previewValue && !isImageType()" class="fa fa-eye"
                                   (click)="previewFiles($event, downloadId)">
                                    <a download (click)="downloadFile()" #downloadId style="display:none;"></a>
                                </i>
                                <i *ngIf="files[0] && !disabled" class="fa fa-trash-alt"
                                   (click)="removeFiles($event, this)"></i>
                            </button>
                        </div>
                        <mat-label>{{ fileName }}</mat-label>
                    </mat-card-actions>
                    <mat-card-content>
                    </mat-card-content>
                </mat-card>
                <mat-error
                  *ngIf="sizeError!==null">{{ sizeError + ' ' + ('common.is.over-size' | translate) }}
                </mat-error>
                <mat-error
                  *ngIf="typeError!==null">{{ typeError + ' ' + ('common.is.not-accept' | translate) }}
                </mat-error>
                <mat-error *ngIf="getRequiredErr()">{{ ('common.error.required' | translate) }}</mat-error>
                <mat-error *ngIf="widthError">{{ ('common.error.image.width' | translate) }}</mat-error>
                <mat-error *ngIf="heightError">{{ ('common.error.image.height' | translate) }}</mat-error>
                <mat-error *ngIf="isSquareError">{{ ('common.error.image.square' | translate) }}</mat-error>
                <mat-error *ngIf="isRectangleError">{{ ('common.error.image.rectangle' | translate) }}</mat-error>
            </div>
        </div>
    `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "component", type: i3$3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3$3.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i3$3.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "directive", type: DragDropDirective, selector: "[appDragDrop]", outputs: ["onFileDropped"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "pipe", type: SecureImgPipe, name: "secure" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaUploadFileComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-upload-file',
                    standalone: false,
                    template: `
        <div class="cva-multi-upload labelOutside"
             fxLayout="row" fxLayout.lt-sm="row wrap">
            <mat-label *ngIf="label" class="label_width"
                       fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
                <div class="label">{{ (label ? label : '') | translate }}<span
                  class="required-label-outside">{{ !!required ? '*' : '' }}</span></div>
            </mat-label>
            <div class="uploadArea" style="background-color: #FFFFFF"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%"
                 appDragDrop (onFileDropped)="onFileDroppedAction($event)">
                <input type="file" #fileUpload (change)="onFileChangeAction($event)"
                       [disabled]="disabled"
                       accept="{{accept ? accept.join() : '*/*'}}">
                <mat-card>
                    <mat-card-actions>
                        <div fxLayout="column">
                            <button mat-button
                                    class="{{(isImageType() && files[0])?'upload-button preview': 'upload-button'}}"
                                    color="warn" (click)="onClick()">
                                <div class="preview-image"
                                     *ngIf="isImageType() && files[0]">
                                    <img (load)="onLoad(img, $event)"
                                         #img
                                         style="display: none"
                                         [src]="getSrcImg()| secure | async"
                                         *ngIf="isImageType() && files[0]"
                                    />
                                </div>
                                <i [ngClass]="files[0]?'fa fa-file-alt':'fa fa-plus'"
                                   *ngIf="!isImageType()  || !files[0]"></i>
                                <span
                                  *ngIf="!files[0]">{{ ((placeholder ? placeholder : 'common.button.import.file')| translate) }}</span>
                                <i *ngIf="!!files[0]?.previewValue && !isImageType()" class="fa fa-eye"
                                   (click)="previewFiles($event, downloadId)">
                                    <a download (click)="downloadFile()" #downloadId style="display:none;"></a>
                                </i>
                                <i *ngIf="files[0] && !disabled" class="fa fa-trash-alt"
                                   (click)="removeFiles($event, this)"></i>
                            </button>
                        </div>
                        <mat-label>{{ fileName }}</mat-label>
                    </mat-card-actions>
                    <mat-card-content>
                    </mat-card-content>
                </mat-card>
                <mat-error
                  *ngIf="sizeError!==null">{{ sizeError + ' ' + ('common.is.over-size' | translate) }}
                </mat-error>
                <mat-error
                  *ngIf="typeError!==null">{{ typeError + ' ' + ('common.is.not-accept' | translate) }}
                </mat-error>
                <mat-error *ngIf="getRequiredErr()">{{ ('common.error.required' | translate) }}</mat-error>
                <mat-error *ngIf="widthError">{{ ('common.error.image.width' | translate) }}</mat-error>
                <mat-error *ngIf="heightError">{{ ('common.error.image.height' | translate) }}</mat-error>
                <mat-error *ngIf="isSquareError">{{ ('common.error.image.square' | translate) }}</mat-error>
                <mat-error *ngIf="isRectangleError">{{ ('common.error.image.rectangle' | translate) }}</mat-error>
            </div>
        </div>
    `,
                }]
        }], ctorParameters: () => [{ type: i1$3.HttpClient }, { type: i0.Injector }, { type: i2$1.FileSaverService }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { fileUpload: [{
                type: ViewChild,
                args: ['fileUpload', { static: false }]
            }], files: [{
                type: Input
            }], maxSize: [{
                type: Input
            }], height: [{
                type: Input
            }], width: [{
                type: Input
            }], isSquareImg: [{
                type: Input
            }], isRectangleImg: [{
                type: Input
            }], accept: [{
                type: Input
            }], label: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], required: [{
                type: Input
            }], disabled: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], onFileChange: [{
                type: Output
            }], onFileDelete: [{
                type: Output
            }], value: [{
                type: Input
            }], defaultUrl: [{
                type: Input
            }] } });

class CvaMultiUploadImgComponent {
    injector;
    ngControl;
    files = [];
    formArray = new FormArray([]);
    isFix = false;
    maxControls = -1;
    disabled = false;
    constructor(injector, ngControl) {
        this.injector = injector;
        this.ngControl = ngControl;
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    get FileTypes() {
        return FileTypeEnum;
    }
    getControls() {
        return this.formArray.controls;
    }
    writeValue(value) {
        this.formArray.clear();
        const remain = this.isFix ? (this.maxControls === -1 ? value.length : this.maxControls)
            : (this.maxControls === -1 ? (value.length + 1) : this.maxControls);
        for (let i = 0; i < remain; i++) {
            const url = i < value.length ? value[i] : '';
            this.formArray.push(new FormGroup({
                imageUrl: new FormControl(url),
            }));
        }
        this.formArray.valueChanges.subscribe(res => {
            this.propagateChange(res);
        });
    }
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    onFileDelete(event) {
        if (this.isFix) {
            return;
        }
        this.formArray.removeAt(event.index);
        if ((this.formArray.length + 1) === this.maxControls) {
            this.formArray.push(new FormGroup({
                imageUrl: new FormControl(''),
            }));
        }
    }
    onFileChange(event) {
        if ((event.index < this.formArray.length - 1) || this.isFix || (event.index === this.maxControls - 1)) {
            return;
        }
        this.formArray.push(new FormGroup({
            imageUrl: new FormControl(''),
        }));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaMultiUploadImgComponent, deps: [{ token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaMultiUploadImgComponent, isStandalone: false, selector: "cva-multi-upload-img", inputs: { isFix: "isFix", maxControls: "maxControls", disabled: "disabled" }, ngImport: i0, template: `
        <div style="align-items: flex-start" fxLayout="row wrap">
            <ng-container *ngFor="let control of getControls(); let i = index" [formGroup]="control">
                <cva-upload-file style="margin-right: 20px"
                                formControlName="imageUrl" (onFileDelete)="onFileDelete({control:control, index:i})"
                                (onFileChange)="onFileChange({control:control, index:i})"
                                [defaultUrl]="{url: '', name: ' ', type: 'image/png'}"
                                [accept]="[FileTypes.PNG, FileTypes.JPG]"
                                [disabled]="disabled"
                ></cva-upload-file>
            </ng-container>
        </div>
    `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "component", type: CvaUploadFileComponent, selector: "cva-upload-file", inputs: ["files", "maxSize", "height", "width", "isSquareImg", "isRectangleImg", "accept", "label", "placeholder", "required", "disabled", "percentOfLabelOutside", "value", "defaultUrl"], outputs: ["onFileChange", "onFileDelete"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaMultiUploadImgComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-multi-upload-img',
                    standalone: false,
                    template: `
        <div style="align-items: flex-start" fxLayout="row wrap">
            <ng-container *ngFor="let control of getControls(); let i = index" [formGroup]="control">
                <cva-upload-file style="margin-right: 20px"
                                formControlName="imageUrl" (onFileDelete)="onFileDelete({control:control, index:i})"
                                (onFileChange)="onFileChange({control:control, index:i})"
                                [defaultUrl]="{url: '', name: ' ', type: 'image/png'}"
                                [accept]="[FileTypes.PNG, FileTypes.JPG]"
                                [disabled]="disabled"
                ></cva-upload-file>
            </ng-container>
        </div>
    `,
                }]
        }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { isFix: [{
                type: Input
            }], maxControls: [{
                type: Input
            }], disabled: [{
                type: Input
            }] } });

class CvaBreadcrumbComponent {
    activatedRoute;
    breadcrumbList = [];
    updateLabel = new EventEmitter();
    constructor(activatedRoute) {
        this.activatedRoute = activatedRoute;
    }
    ngOnInit() {
        this.breadcrumbList = this.buildBreadCrumb(this.activatedRoute.root);
    }
    buildBreadCrumb(route, url = '', breadcrumbs = []) {
        let label = route.routeConfig
            ? (route.routeConfig.data ? route.routeConfig.data['breadcrumb'] : 'common.missing.router.data.breadcrumb')
            : '';
        if (this.updateLabel.observers.length > 0) {
            const out = { label };
            this.updateLabel.emit(out);
            label = out.label;
        }
        let path = route.routeConfig && route.routeConfig.path ? route.routeConfig.path : '';
        if (route.snapshot && route.snapshot.params) {
            Object.keys(route.snapshot.params).forEach(key => {
                label = label.replace(':' + key, route.snapshot.params[key]);
                path = path.replace(':' + key, route.snapshot.params[key]);
            });
        }
        const nextUrl = `${url}${path}/`;
        if (nextUrl.endsWith('//')) {
            return breadcrumbs;
        }
        const breadcrumb = new BreadCrumbModel(label, nextUrl);
        const newBreadcrumbs = [...breadcrumbs, breadcrumb];
        if (route.firstChild) {
            return this.buildBreadCrumb(route.firstChild, nextUrl, newBreadcrumbs);
        }
        return newBreadcrumbs;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaBreadcrumbComponent, deps: [{ token: i1$4.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaBreadcrumbComponent, isStandalone: false, selector: "cva-breadcrumb", outputs: { updateLabel: "updateLabel" }, ngImport: i0, template: `
    <ul class="cva-breadcrumb">
      <div class="breadcrumbList">
        <li *ngFor="let item of breadcrumbList; let i = index">
          <a [routerLink]="'/' + item.url" *ngIf="i!==breadcrumbList.length-1">
            {{ item.label | translate }}
          </a>
          <span class="separator" *ngIf="i!==breadcrumbList.length-1"> <i class="fa fa-angle-right"></i> </span>
          <span class="currentAction" *ngIf="i===breadcrumbList.length-1">{{ item.label | translate }}</span>
        </li>
      </div>
    </ul>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaBreadcrumbComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-breadcrumb',
                    standalone: false,
                    template: `
    <ul class="cva-breadcrumb">
      <div class="breadcrumbList">
        <li *ngFor="let item of breadcrumbList; let i = index">
          <a [routerLink]="'/' + item.url" *ngIf="i!==breadcrumbList.length-1">
            {{ item.label | translate }}
          </a>
          <span class="separator" *ngIf="i!==breadcrumbList.length-1"> <i class="fa fa-angle-right"></i> </span>
          <span class="currentAction" *ngIf="i===breadcrumbList.length-1">{{ item.label | translate }}</span>
        </li>
      </div>
    </ul>
  `,
                }]
        }], ctorParameters: () => [{ type: i1$4.ActivatedRoute }], propDecorators: { updateLabel: [{
                type: Output
            }] } });

class CvaLoaderComponent {
    loaderService;
    imgSrc = '';
    constructor(loaderService) {
        this.loaderService = loaderService;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaLoaderComponent, deps: [{ token: LoaderService }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaLoaderComponent, isStandalone: false, selector: "cva-loader", inputs: { imgSrc: "imgSrc" }, ngImport: i0, template: `
        <div class="cva-loader progress-loader" *ngIf="loaderService.isLoading | async">
            <div class="loading-spinner">
                <mat-progress-bar color="warn" mode="indeterminate">
                </mat-progress-bar>
                <mat-progress-spinner color="warn" mode="indeterminate" diameter="200" strokeWidth="15">
                </mat-progress-spinner>
            </div>
            <img *ngIf="!!imgSrc" [src]="imgSrc"  alt=""/>
        </div>
    `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3$4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i9$2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaLoaderComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-loader',
                    standalone: false,
                    template: `
        <div class="cva-loader progress-loader" *ngIf="loaderService.isLoading | async">
            <div class="loading-spinner">
                <mat-progress-bar color="warn" mode="indeterminate">
                </mat-progress-bar>
                <mat-progress-spinner color="warn" mode="indeterminate" diameter="200" strokeWidth="15">
                </mat-progress-spinner>
            </div>
            <img *ngIf="!!imgSrc" [src]="imgSrc"  alt=""/>
        </div>
    `,
                }]
        }], ctorParameters: () => [{ type: LoaderService }], propDecorators: { imgSrc: [{
                type: Input
            }] } });

class CvaTreeComponent {
    _treeFields = new FlatTreeModel();
    autocompleteData = [];
    set treeData(treeFields) {
        if (treeFields && treeFields.rootData && treeFields.rootData.length > 0) {
            this._treeFields = treeFields;
            this.autocompleteData = UtilsService.convertTreeDataToAutocompleteData(this._treeFields, this.symbol, this.hasChild, this._treeFields.rootData, null);
            this.onSelectChange();
        }
    }
    placeholder = '';
    symbol = ' >> ';
    isShowLeafNextTo = false;
    disabled = false;
    isHidingTree = false;
    selectionChange = new EventEmitter();
    treeControl = new NestedTreeControl(node => {
        return this._treeFields && this._treeFields.children ? this._treeFields.children(node) : [];
    });
    dataSource = new MatTreeNestedDataSource();
    autocompleteControl = new FormControl();
    constructor() {
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    writeValue(obj) {
        if (this._treeFields) {
            this.dataSource.data = this._treeFields.rootData;
            this.treeControl.dataNodes = this._treeFields.rootData;
            if (obj) {
                this.updateTreeChecked(this._treeFields.rootData, obj);
                this.autocompleteControl.setValue(obj);
                this.propagateChange(obj);
                this.selectionChange.emit(obj);
            }
        }
    }
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    hasChild = (_, node) => {
        if (this._treeFields && this._treeFields.children) {
            const children = this._treeFields.children(node);
            return children && children.length > 0;
        }
        return false;
    };
    onSelectChange() {
        const selectedValues = this.autocompleteControl.value;
        this.writeValue(selectedValues);
        this.treeControl.collapseAll();
    }
    updateTreeChecked(nodes, selectedValues) {
        if (this._treeFields) {
            for (const node of nodes) {
                if (this.hasChild(0, node)) {
                    this.updateTreeChecked(this._treeFields.children(node), selectedValues);
                }
                else {
                    node.checked = !selectedValues || selectedValues.length === 0; // Nếu selectedValues.length === 0 thì showAll
                    if (selectedValues && selectedValues.length > 0) {
                        const value = this._treeFields.value(node).toString().toLowerCase();
                        if (selectedValues instanceof Array) {
                            selectedValues.forEach((selectedValue) => {
                                node.checked = node.checked || value === selectedValue.toLowerCase();
                                if (node.checked) {
                                    return;
                                }
                            });
                        }
                        else {
                            node.checked = value === selectedValues.toLowerCase();
                        }
                    }
                }
            }
        }
    }
    isShowNodeRecursive(nodes) {
        let result = false;
        if (this._treeFields) {
            for (const node of nodes) {
                result = result || node.checked
                    || (this.hasChild(0, node) && this.isShowNodeRecursive(this._treeFields.children(node)));
                if (result) {
                    break;
                }
            }
        }
        return result;
    }
    isMatchFilterInputValue(node) {
        const selectedValues = this.autocompleteControl.value;
        if (selectedValues && selectedValues.length > 0) {
            return node.checked ? node.checked : false;
        }
        return false;
    }
    isShowButtonChoose(node) {
        if (this.disabled) {
            return false;
        }
        const selectedValues = this.autocompleteControl.value;
        if (!selectedValues || selectedValues.length <= 0) {
            return false;
        }
        return !node.checked;
    }
    isShowButtonRemove(node) {
        if (this.disabled) {
            return false;
        }
        const selectedValues = this.autocompleteControl.value;
        if (!selectedValues || selectedValues.length <= 0) {
            return false;
        }
        return node.checked ? node.checked : false;
    }
    onChooseNode(node) {
        const selectedValues = this.autocompleteControl.value;
        if (selectedValues && selectedValues.length > 0 && this._treeFields) {
            let isExists = false;
            for (const selectedValue of selectedValues) {
                isExists = isExists || selectedValue.toLowerCase() === this._treeFields.value(node).toString().toLowerCase();
            }
            if (!isExists) {
                selectedValues.push(this._treeFields.value(node).toString());
                this.writeValue(selectedValues);
            }
        }
    }
    onRemoveNode(node) {
        const selectedValues = this.autocompleteControl.value;
        if (selectedValues && selectedValues.length > 0 && this._treeFields) {
            const index = selectedValues.indexOf(this._treeFields.value(node).toString());
            if (index >= 0) {
                selectedValues.splice(index, 1);
                this.writeValue(selectedValues);
            }
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaTreeComponent, isStandalone: false, selector: "cva-tree", inputs: { treeData: "treeData", placeholder: "placeholder", symbol: "symbol", isShowLeafNextTo: "isShowLeafNextTo", disabled: "disabled", isHidingTree: "isHidingTree" }, outputs: { selectionChange: "selectionChange" }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => CvaTreeComponent),
                multi: true,
            },
        ], ngImport: i0, template: `
      <div class="cva-tree">
          <div class="box-search">
              <cva-multi-select-autocomplete [multiple]="!isHidingTree" [placeholder]="placeholder|translate"
                                            [options]="autocompleteData" style="width: 100%"
                                            [formControl]="autocompleteControl" [disabled]="disabled"
                                            (selectionChange)="onSelectChange()"
                                            [isTree]="true" [treeSymbol]="symbol">
              </cva-multi-select-autocomplete>
              <div class="expand_collapse" *ngIf="!isHidingTree">
                  <button mat-icon-button color="warn" (click)="treeControl.collapseAll()"
                          matTooltip="{{'common.tree.collapseAll'|translate}}">
                      <mat-icon>unfold_less</mat-icon>
                  </button>
                  <button mat-icon-button color="warn" (click)="treeControl.expandAll()"
                          matTooltip="{{'common.tree.expandAll'|translate}}">
                      <mat-icon>unfold_more</mat-icon>
                  </button>
              </div>
          </div>
          <div class="parent-mat-tree" *ngIf="!isHidingTree">
              <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree">
                  <!-- This is the tree node template for leaf nodes -->
                  <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle
                                 [ngClass]="{'example-tree-invisible': !isShowLeafNextTo && !isShowNodeRecursive([node]),
                                'mat-tree-node': isShowNodeRecursive([node])}">
                      <li fxLayoutAlign="space-between center" fxLayout>
                          <div class="mat-tree-node">
                              <!-- use a disabled button to provide padding for tree leaf -->
                              <button mat-icon-button disabled></button>
                              <label [ngClass]="{'item-focused': isMatchFilterInputValue(node)}">
                                  {{_treeFields.display(node)}}</label>
                          </div>
                          <div class="mat-tree-node-button">
                              <button mat-icon-button color="warn" (click)="onChooseNode(node)"
                                      *ngIf="isShowButtonChoose(node)"
                                      matTooltip="{{'common.tree.add'|translate}}">
                                  <mat-icon>add</mat-icon>
                              </button>
                              <button mat-icon-button color="warn" (click)="onRemoveNode(node)"
                                      *ngIf="isShowButtonRemove(node)"
                                      matTooltip="{{'common.tree.remove'|translate}}">
                                  <mat-icon>clear</mat-icon>
                              </button>
                          </div>
                      </li>
                  </mat-tree-node>
                  <!-- This is the tree node template for expandable nodes -->
                  <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild"
                                        [ngClass]="{'example-tree-invisible': !isShowNodeRecursive([node])}">
                      <li>
                          <div class="mat-tree-node">
                              <button mat-icon-button matTreeNodeToggle
                                      [attr.aria-label]="'toggle ' + _treeFields.value(node)">
                                  <mat-icon class="mat-icon-rtl-mirror">
                                      {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
                                  </mat-icon>
                              </button>
                              <label [ngClass]="{'item-focused': isMatchFilterInputValue(node)}">
                                  {{_treeFields.display(node)}}</label>
                          </div>
                          <ul *ngIf="!treeControl.isExpanded(node)">
                              <ng-container matTreeNodeOutlet></ng-container>
                          </ul>
                      </li>
                  </mat-nested-tree-node>
              </mat-tree>
          </div>
      </div>
  `, isInline: true, 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: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i8$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i6$1.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i6$1.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: i6$1.MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "component", type: i6$1.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i6$1.MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "directive", type: i6$1.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "component", type: CvaMultiSelectAutocomplete, selector: "cva-multi-select-autocomplete", inputs: ["placeholder", "label", "hint", "value", "options", "disabled", "errorMessages", "multiple", "required", "isTree", "treeSymbol", "sizeOfItemsInListByPixels", "isLabelOutside", "isFloatLabel", "percentOfLabelOutside", "isFormControl"], outputs: ["selectionChange", "selectedOptionDataChange"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaTreeComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-tree',
                    standalone: false,
                    template: `
      <div class="cva-tree">
          <div class="box-search">
              <cva-multi-select-autocomplete [multiple]="!isHidingTree" [placeholder]="placeholder|translate"
                                            [options]="autocompleteData" style="width: 100%"
                                            [formControl]="autocompleteControl" [disabled]="disabled"
                                            (selectionChange)="onSelectChange()"
                                            [isTree]="true" [treeSymbol]="symbol">
              </cva-multi-select-autocomplete>
              <div class="expand_collapse" *ngIf="!isHidingTree">
                  <button mat-icon-button color="warn" (click)="treeControl.collapseAll()"
                          matTooltip="{{'common.tree.collapseAll'|translate}}">
                      <mat-icon>unfold_less</mat-icon>
                  </button>
                  <button mat-icon-button color="warn" (click)="treeControl.expandAll()"
                          matTooltip="{{'common.tree.expandAll'|translate}}">
                      <mat-icon>unfold_more</mat-icon>
                  </button>
              </div>
          </div>
          <div class="parent-mat-tree" *ngIf="!isHidingTree">
              <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree">
                  <!-- This is the tree node template for leaf nodes -->
                  <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle
                                 [ngClass]="{'example-tree-invisible': !isShowLeafNextTo && !isShowNodeRecursive([node]),
                                'mat-tree-node': isShowNodeRecursive([node])}">
                      <li fxLayoutAlign="space-between center" fxLayout>
                          <div class="mat-tree-node">
                              <!-- use a disabled button to provide padding for tree leaf -->
                              <button mat-icon-button disabled></button>
                              <label [ngClass]="{'item-focused': isMatchFilterInputValue(node)}">
                                  {{_treeFields.display(node)}}</label>
                          </div>
                          <div class="mat-tree-node-button">
                              <button mat-icon-button color="warn" (click)="onChooseNode(node)"
                                      *ngIf="isShowButtonChoose(node)"
                                      matTooltip="{{'common.tree.add'|translate}}">
                                  <mat-icon>add</mat-icon>
                              </button>
                              <button mat-icon-button color="warn" (click)="onRemoveNode(node)"
                                      *ngIf="isShowButtonRemove(node)"
                                      matTooltip="{{'common.tree.remove'|translate}}">
                                  <mat-icon>clear</mat-icon>
                              </button>
                          </div>
                      </li>
                  </mat-tree-node>
                  <!-- This is the tree node template for expandable nodes -->
                  <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild"
                                        [ngClass]="{'example-tree-invisible': !isShowNodeRecursive([node])}">
                      <li>
                          <div class="mat-tree-node">
                              <button mat-icon-button matTreeNodeToggle
                                      [attr.aria-label]="'toggle ' + _treeFields.value(node)">
                                  <mat-icon class="mat-icon-rtl-mirror">
                                      {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
                                  </mat-icon>
                              </button>
                              <label [ngClass]="{'item-focused': isMatchFilterInputValue(node)}">
                                  {{_treeFields.display(node)}}</label>
                          </div>
                          <ul *ngIf="!treeControl.isExpanded(node)">
                              <ng-container matTreeNodeOutlet></ng-container>
                          </ul>
                      </li>
                  </mat-nested-tree-node>
              </mat-tree>
          </div>
      </div>
  `,
                    providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => CvaTreeComponent),
                            multi: true,
                        },
                    ],
                }]
        }], ctorParameters: () => [], propDecorators: { treeData: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], symbol: [{
                type: Input
            }], isShowLeafNextTo: [{
                type: Input
            }], disabled: [{
                type: Input
            }], isHidingTree: [{
                type: Input
            }], selectionChange: [{
                type: Output
            }] } });

class CvaRadiobuttonComponent {
    injector;
    placeholder = '';
    value;
    hint = '';
    options = [];
    disabled = false;
    required = false;
    direction = 'horizontal';
    errorMessages = new Map();
    onChange = new EventEmitter();
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    control = undefined;
    get selectedValue() {
        return this.value;
    }
    set selectedValue(val) {
        this.writeValue(val);
    }
    get NsValidator() {
        return ValidatorService;
    }
    constructor(injector, ngControl) {
        this.injector = injector;
        if (ngControl) {
            ngControl.valueAccessor = this;
        }
    }
    ngOnChanges() {
        this.writeValue(this.value);
    }
    ngOnInit() {
        this.callValidator();
    }
    writeValue(value) {
        if (value !== undefined) {
            this.value = value;
            this.propagateChange(this.value);
            this.callValidator();
            this.onChange.emit(this.value);
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.control) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.control = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.control = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.control) {
                if (this.control.validator) {
                    if (this.required) {
                        this.control.setValidators([Validators.required, this.control.validator]);
                    }
                    else {
                        this.control.setValidators([this.control.validator]);
                    }
                }
                else {
                    if (this.required) {
                        this.control.setValidators([Validators.required]);
                    }
                }
            }
        }
        if (this.control) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.control.setValue(this.selectedValue);
            }
            // Nếu là parent FormControl rồi thì kệ
            this.control.updateValueAndValidity();
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaRadiobuttonComponent, deps: [{ token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaRadiobuttonComponent, isStandalone: false, selector: "cva-radiobutton", inputs: { placeholder: "placeholder", value: "value", hint: "hint", options: "options", disabled: "disabled", required: "required", direction: "direction", errorMessages: "errorMessages", isFormControl: "isFormControl" }, outputs: { onChange: "onChange" }, usesOnChanges: true, ngImport: i0, template: `
    <div class="cva-radiobutton ábc {{!!placeholder ? 'labelOutside' : ''}}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label id="example-radio-group-label" *ngIf="!!placeholder" class="label_width"
             fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{placeholder | translate}}<span class="required-label-outside">{{!!required ? '*' : ''}}</span>
          </div>
        </div>
      </mat-label>
      <div fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-radio-group
            aria-labelledby="example-radio-group-label"
            class="example-radio-group" [disabled]="disabled"
            [(ngModel)]="selectedValue"
            fxLayout="{{direction === 'horizontal' ? 'row' : 'column'}}">
          <mat-radio-button class="example-radio-button"
                            *ngFor="let option of options"
                            [value]="option.value"
                            [disabled]="option.disabled">
            {{option.displayValue | translate}}
          </mat-radio-button>
        </mat-radio-group>
        <mat-hint align="start" *ngIf="!NsValidator.invalid(control) && !hint">{{hint | translate}}</mat-hint>
        <mat-hint align="start" *ngIf="NsValidator.invalid(control)">{{NsValidator.getErrorMessage(control, errorMessages) | translate}}</mat-hint>
      </div>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4$3.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i4$3.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaRadiobuttonComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-radiobutton',
                    standalone: false,
                    template: `
    <div class="cva-radiobutton ábc {{!!placeholder ? 'labelOutside' : ''}}"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label id="example-radio-group-label" *ngIf="!!placeholder" class="label_width"
             fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{placeholder | translate}}<span class="required-label-outside">{{!!required ? '*' : ''}}</span>
          </div>
        </div>
      </mat-label>
      <div fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <mat-radio-group
            aria-labelledby="example-radio-group-label"
            class="example-radio-group" [disabled]="disabled"
            [(ngModel)]="selectedValue"
            fxLayout="{{direction === 'horizontal' ? 'row' : 'column'}}">
          <mat-radio-button class="example-radio-button"
                            *ngFor="let option of options"
                            [value]="option.value"
                            [disabled]="option.disabled">
            {{option.displayValue | translate}}
          </mat-radio-button>
        </mat-radio-group>
        <mat-hint align="start" *ngIf="!NsValidator.invalid(control) && !hint">{{hint | translate}}</mat-hint>
        <mat-hint align="start" *ngIf="NsValidator.invalid(control)">{{NsValidator.getErrorMessage(control, errorMessages) | translate}}</mat-hint>
      </div>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { placeholder: [{
                type: Input
            }], value: [{
                type: Input
            }], hint: [{
                type: Input
            }], options: [{
                type: Input
            }], disabled: [{
                type: Input
            }], required: [{
                type: Input
            }], direction: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], onChange: [{
                type: Output
            }], isFormControl: [{
                type: Input
            }] } });

class FlatTreeService {
    static hasChild(_nodeData) {
        return !!_nodeData.children && Array.isArray(_nodeData.children) && _nodeData.children.length > 0;
    }
    static convertTreeToFlatTree(inputData, config) {
        if (!inputData) {
            return [];
        }
        inputData.forEach(node => {
            this.setRequiredFlatNoteProperty(node, config);
            if (node.children && node.children.length > 0) {
                this.convertTreeToFlatTree(node.children, config);
            }
        });
        return inputData;
    }
    static setRequiredFlatNoteProperty(node, config) {
        node.children = (node.children && node.children.length > 0) ? node.children : null;
        node._displayFuncInput = config.isDynamicConfig ? config.display : typeof (config.display) === 'function' ? config.display(node) : config.display;
        node.display = typeof node._displayFuncInput === 'function' ? node._displayFuncInput(node) : node._displayFuncInput;
        node._disabledFuncInput = config.isDynamicConfig ? config.disabled : typeof (config.disabled) === 'function' ? config.disabled(node) : config.disabled;
        node.disabled = typeof node._disabledFuncInput === 'function' ? node._disabledFuncInput(node) : node._disabledFuncInput;
        return node;
    }
}

class CvaFlatTreeNodeLeftComponent {
    treeControl;
    isHideCheckbox = false;
    node = new FlatTreeNodeModel();
    toggle = new EventEmitter();
    onParentNodeClick = new EventEmitter();
    onLeafNodeClick = new EventEmitter();
    ngModelParentChange = new EventEmitter();
    ngModelLeafChange = new EventEmitter();
    nodeClicked;
    menubar = menubar;
    hasChild = (node) => !!node.children && Array.isArray(node.children) && node.children.length > 0;
    checkDisabledNode(node) {
        return node.disabled || this.getDisabledInputFunc(node);
    }
    getDisabledInputFunc(node) {
        return typeof (node._disabledFuncInput) === 'function' ? node._disabledFuncInput(node) : !!node._disabledFuncInput;
    }
    descendantsAllSelected(node) {
        if (this.treeControl) {
            const descendants = this.treeControl.getDescendants(node);
            return descendants.length > 0 && descendants.every(child => {
                return child.checked;
            });
        }
        return false;
    }
    descendantsPartiallySelected(node) {
        if (this.treeControl) {
            const descendants = this.treeControl.getDescendants(node);
            const result = descendants.some(child => child.checked);
            return result && !this.descendantsAllSelected(node);
        }
        return false;
    }
    onDisabledParent(parent) {
        if (!parent.disabled) {
            return false;
        }
        else if (this.treeControl) {
            this.treeControl.getDescendants(parent).forEach(childNode => childNode.disabled = true);
            return true;
        }
        else {
            return false;
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaFlatTreeNodeLeftComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaFlatTreeNodeLeftComponent, isStandalone: false, selector: "cva-flat-tree-node-left", inputs: { treeControl: "treeControl", isHideCheckbox: "isHideCheckbox", node: "node", nodeClicked: "nodeClicked" }, outputs: { toggle: "toggle", onParentNodeClick: "onParentNodeClick", onLeafNodeClick: "onLeafNodeClick", ngModelParentChange: "ngModelParentChange", ngModelLeafChange: "ngModelLeafChange" }, ngImport: i0, template: `
    <ng-container [ngSwitch]="hasChild(node)">
      <ng-container *ngSwitchCase="false">
        <div
          class="label-area {{isHideCheckbox ? 'isClickDiv' : ''}} {{isHideCheckbox && nodeClicked?.value === node.value ? 'nodeSelected': ''}}"
          (click)="onLeafNodeClick.emit()"
          fxLayoutAlign="space-between center">
          <button *ngIf="node.level > 0" type="button" mat-icon-button disabled></button>
          {{ node.displayValue }}
        </div>
        <mat-checkbox [(ngModel)]="node.checked"
                      [checked]="node.checked"
                      (ngModelChange)="ngModelLeafChange.emit($event)"
                      [disabled]="checkDisabledNode(node)"
                      *ngIf="!isHideCheckbox">
        </mat-checkbox>
      </ng-container>
      <ng-container *ngSwitchCase="true">
        <div
          class="label-area {{isHideCheckbox ? 'isClickDiv' : ''}} {{isHideCheckbox && nodeClicked?.value === node.value ? 'nodeSelected': ''}}"
          fxLayoutAlign="space-between center">
          <button type="button" mat-icon-button (click)="toggle.emit()"
                  [attr.aria-label]="'toggle ' + node.displayValue">
            <i class="fas {{(treeControl && treeControl.isExpanded(node)) ? 'fa-chevron-up' : 'fa-chevron-down'}}"></i>
          </button>
          <span (click)="onParentNodeClick.emit()">{{ node.displayValue }}</span>
        </div>
        <mat-checkbox [(ngModel)]="node.checked"
                      *ngIf="!isHideCheckbox"
                      [checked]="descendantsAllSelected(node)"
                      [disabled]="onDisabledParent(node) || getDisabledInputFunc(node)"
                      [indeterminate]="descendantsPartiallySelected(node)"
                      (ngModelChange)="ngModelParentChange.emit($event)">
        </mat-checkbox>
      </ng-container>
    </ng-container>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaFlatTreeNodeLeftComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-flat-tree-node-left',
                    standalone: false,
                    template: `
    <ng-container [ngSwitch]="hasChild(node)">
      <ng-container *ngSwitchCase="false">
        <div
          class="label-area {{isHideCheckbox ? 'isClickDiv' : ''}} {{isHideCheckbox && nodeClicked?.value === node.value ? 'nodeSelected': ''}}"
          (click)="onLeafNodeClick.emit()"
          fxLayoutAlign="space-between center">
          <button *ngIf="node.level > 0" type="button" mat-icon-button disabled></button>
          {{ node.displayValue }}
        </div>
        <mat-checkbox [(ngModel)]="node.checked"
                      [checked]="node.checked"
                      (ngModelChange)="ngModelLeafChange.emit($event)"
                      [disabled]="checkDisabledNode(node)"
                      *ngIf="!isHideCheckbox">
        </mat-checkbox>
      </ng-container>
      <ng-container *ngSwitchCase="true">
        <div
          class="label-area {{isHideCheckbox ? 'isClickDiv' : ''}} {{isHideCheckbox && nodeClicked?.value === node.value ? 'nodeSelected': ''}}"
          fxLayoutAlign="space-between center">
          <button type="button" mat-icon-button (click)="toggle.emit()"
                  [attr.aria-label]="'toggle ' + node.displayValue">
            <i class="fas {{(treeControl && treeControl.isExpanded(node)) ? 'fa-chevron-up' : 'fa-chevron-down'}}"></i>
          </button>
          <span (click)="onParentNodeClick.emit()">{{ node.displayValue }}</span>
        </div>
        <mat-checkbox [(ngModel)]="node.checked"
                      *ngIf="!isHideCheckbox"
                      [checked]="descendantsAllSelected(node)"
                      [disabled]="onDisabledParent(node) || getDisabledInputFunc(node)"
                      [indeterminate]="descendantsPartiallySelected(node)"
                      (ngModelChange)="ngModelParentChange.emit($event)">
        </mat-checkbox>
      </ng-container>
    </ng-container>
  `,
                }]
        }], propDecorators: { treeControl: [{
                type: Input
            }], isHideCheckbox: [{
                type: Input
            }], node: [{
                type: Input
            }], toggle: [{
                type: Output
            }], onParentNodeClick: [{
                type: Output
            }], onLeafNodeClick: [{
                type: Output
            }], ngModelParentChange: [{
                type: Output
            }], ngModelLeafChange: [{
                type: Output
            }], nodeClicked: [{
                type: Input
            }] } });

class CvaFlatTreeNodeRightComponent {
    treeControl;
    node = new FlatTreeNodeModel();
    isView = false;
    toggle = new EventEmitter();
    deSelectLeafNode = new EventEmitter();
    deSelectParentNode = new EventEmitter();
    hasChild = (node) => !!node.children && Array.isArray(node.children) && node.children.length > 0;
    checkDisabledNode(node) {
        return node.disabled || this.getDisabledInputFunc(node);
    }
    getDisabledInputFunc(node) {
        return typeof (node._disabledFuncInput) === 'function' ? node._disabledFuncInput(node) : !!node._disabledFuncInput;
    }
    checkIsView(isView) {
        return isView ? typeof (isView) === 'boolean' ? isView : isView() : false;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaFlatTreeNodeRightComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaFlatTreeNodeRightComponent, isStandalone: false, selector: "cva-flat-tree-node-right", inputs: { treeControl: "treeControl", node: "node", isView: "isView" }, outputs: { toggle: "toggle", deSelectLeafNode: "deSelectLeafNode", deSelectParentNode: "deSelectParentNode" }, ngImport: i0, template: `
    <ng-container [ngSwitch]="hasChild(node)">
      <ng-container *ngSwitchCase="false">
        <div style="width: 100%"
             fxLayout="row"
             fxLayoutAlign="space-between center">
          <div class="label-area"
               fxLayout="row"
               fxLayoutAlign="space-between center">
            <button *ngIf="node.level > 0" type="button" mat-icon-button disabled></button>
            {{ node.displayValue }}
          </div>
          <button type="button" mat-icon-button class="danger"
                  *ngIf="!(checkDisabledNode(node) || checkIsView(isView))"
                  (click)="deSelectLeafNode.emit()">
            <i class="far fa-trash-alt"></i>
          </button>
        </div>
      </ng-container>
      <ng-container *ngSwitchCase="true">
        <div style="width: 100%"
             fxLayout="row"
             fxLayoutAlign="space-between center">
          <div class="label-area"
               fxLayout="row"
               fxLayoutAlign="space-between center">
            <button type="button" mat-icon-button (click)="toggle.emit()"
                    [attr.aria-label]="'toggle ' + node.displayValue">
              <i class="fas {{treeControl?.isExpanded(node) ? 'fa-chevron-up' : 'fa-chevron-down'}}"></i>
            </button>
            {{ node.displayValue }}
          </div>
          <button type="button" mat-icon-button class="danger"
                  *ngIf="!(checkDisabledNode(node) || checkIsView(isView))"
                  (click)="deSelectParentNode.emit()">
            <i class="far fa-trash-alt"></i>
          </button>
        </div>
      </ng-container>
    </ng-container>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultLayoutAlignDirective, selector: "  [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md],  [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md],  [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm],  [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaFlatTreeNodeRightComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-flat-tree-node-right',
                    standalone: false,
                    template: `
    <ng-container [ngSwitch]="hasChild(node)">
      <ng-container *ngSwitchCase="false">
        <div style="width: 100%"
             fxLayout="row"
             fxLayoutAlign="space-between center">
          <div class="label-area"
               fxLayout="row"
               fxLayoutAlign="space-between center">
            <button *ngIf="node.level > 0" type="button" mat-icon-button disabled></button>
            {{ node.displayValue }}
          </div>
          <button type="button" mat-icon-button class="danger"
                  *ngIf="!(checkDisabledNode(node) || checkIsView(isView))"
                  (click)="deSelectLeafNode.emit()">
            <i class="far fa-trash-alt"></i>
          </button>
        </div>
      </ng-container>
      <ng-container *ngSwitchCase="true">
        <div style="width: 100%"
             fxLayout="row"
             fxLayoutAlign="space-between center">
          <div class="label-area"
               fxLayout="row"
               fxLayoutAlign="space-between center">
            <button type="button" mat-icon-button (click)="toggle.emit()"
                    [attr.aria-label]="'toggle ' + node.displayValue">
              <i class="fas {{treeControl?.isExpanded(node) ? 'fa-chevron-up' : 'fa-chevron-down'}}"></i>
            </button>
            {{ node.displayValue }}
          </div>
          <button type="button" mat-icon-button class="danger"
                  *ngIf="!(checkDisabledNode(node) || checkIsView(isView))"
                  (click)="deSelectParentNode.emit()">
            <i class="far fa-trash-alt"></i>
          </button>
        </div>
      </ng-container>
    </ng-container>
  `,
                }]
        }], propDecorators: { treeControl: [{
                type: Input
            }], node: [{
                type: Input
            }], isView: [{
                type: Input
            }], toggle: [{
                type: Output
            }], deSelectLeafNode: [{
                type: Output
            }], deSelectParentNode: [{
                type: Output
            }] } });

class CvaFlatTreeComponent {
    translateService;
    injector;
    cdr;
    label = '';
    required = false;
    value = [];
    valueObjRef = new Map();
    multiple = true;
    disabled;
    isView = false;
    isDisplayChooseTreeOnly = false;
    isHideCheckbox = false;
    isCollapseSelected = false;
    selectedLabelTitle = 'common.selected.tree.label';
    /** height of tree view */
    viewHeight = 300; // px
    /** height of node view */
    itemSize = 48; // px
    paddingLeft = 20; //px
    /* percent label outside css */
    percentOfLabelOutside = 25;
    treeConfig;
    isSearchOutSide = false;
    searchTextOutSide = '';
    searchText = '';
    errorMessages = new Map();
    fullDatasource = [];
    filterDatasource = [];
    treeControl;
    treeFlattener;
    dataSource;
    fullDataTreeControl;
    fullDataTreeFlattener;
    fullDataDataSource;
    selectedTreeControl;
    selectedTreeFlattener;
    selectedDataSource;
    selectedFullDataSource = [];
    selectedFullValues = new Map();
    selectionChange = new EventEmitter();
    onNodeClick = new EventEmitter();
    nodeClicked;
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    // Cái này là để gắn khi nó là FormControl trong 1 FormGroup
    formControl;
    mapIndexes = new Map();
    chooseVirtualScroll;
    selectedVirtualScroll;
    constructor(translateService, injector, cdr, ngControl) {
        this.translateService = translateService;
        this.injector = injector;
        this.cdr = cdr;
        if (ngControl) {
            ngControl.valueAccessor = this;
        }
        this.fullDataTreeFlattener = new MatTreeFlattener(this.transformer, this._getLevel, this._isExpandable, this._getChildren);
        this.fullDataTreeControl = new FlatTreeControl(this._getLevel, this._isExpandable);
        this.fullDataDataSource = new MatTreeFlatDataSource(this.fullDataTreeControl, this.fullDataTreeFlattener);
        this.fullDataDataSource.data = this.fullDatasource;
        this.treeFlattener = new MatTreeFlattener(this.transformer, this._getLevel, this._isExpandable, this._getChildren);
        this.treeControl = new FlatTreeControl(this._getLevel, this._isExpandable);
        this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
        this.setDataSourceOrigin();
        this.selectedTreeFlattener = new MatTreeFlattener(this.transformer, this._getLevel, this._isExpandable, this._getChildren);
        this.selectedTreeControl = new FlatTreeControl(this._getLevel, this._isExpandable);
        this.selectedDataSource = new MatTreeFlatDataSource(this.selectedTreeControl, this.selectedTreeFlattener);
        this.setSelectedNode();
    }
    get NsValiator() {
        return ValidatorService;
    }
    setSelectedNode() {
        this.selectedDataSource.data = this.selectedFullDataSource;
        if (this.selectedVirtualScroll) {
            this.selectedVirtualScroll.checkViewportSize();
        }
    }
    setDataSourceOrigin() {
        this.fullDataDataSource.data = this.fullDatasource;
        this.dataSource.data = this.filterDatasource;
        if (this.chooseVirtualScroll) {
            this.chooseVirtualScroll.checkViewportSize();
        }
    }
    ngOnInit() {
        this.callValidator();
    }
    ngAfterViewInit() {
        // this.onChangeSearchText();
    }
    getDisplayInputFunc(node) {
        return typeof (node._displayFuncInput) === 'function' ? node._displayFuncInput(node) : !!node._displayFuncInput;
    }
    getDisabledInputFunc(node) {
        return typeof (node._disabledFuncInput) === 'function' ? node._disabledFuncInput(node) : !!node._disabledFuncInput;
    }
    checkDisabledNode(node) {
        return node.disabled || this.getDisabledInputFunc(node);
    }
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        if (ngControl && !this.formControl) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.formControl = ngControl.control ? ngControl.control : undefined;
                if (this.formControl && !this.formControl.value) {
                    this.formControl.setValue(this.value);
                }
            }
            else {
                this.formControl = new FormControl();
            }
            if (this.formControl) {
                // this.formControl.setValidators(NsValidator.generateNsMultiSelectValidators({
                //   required: this.required,
                // }));
            }
        }
        if (this.formControl) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.formControl.setValue(this.value);
            }
            this.formControl.updateValueAndValidity();
            const errorsObj = {};
            const errors = this.formControl.errors;
            if (errors) {
                Object.keys(errors).forEach(key => {
                    errorsObj[key] = errors[key];
                });
            }
            if (this.checkRequired(this.required)) {
                if (Array.isArray(this.value) && this.value.length === 0) {
                    errorsObj['required'] = true;
                }
            }
            if (Object.keys(errorsObj).length > 0) {
                this.formControl.setErrors(errorsObj);
            }
            else {
                this.formControl.setErrors(null);
            }
            this.formControl.markAllAsTouched();
        }
    }
    checkRequired(isRequired) {
        return isRequired ? typeof (isRequired) === 'boolean' ? isRequired : isRequired() : false;
    }
    checkIsView(isView) {
        return isView ? typeof (isView) === 'boolean' ? isView : isView() : false;
    }
    ngOnChanges(simpleChanges) {
        if ('fullDatasource' in simpleChanges) {
            // this.fullDatasource = simpleChanges.fullDatasource.currentValue;
            if (!this.treeConfig) {
                this.treeConfig = new FlatTreeConfigModel();
            }
            const currentSource = simpleChanges.fullDatasource.currentValue ? simpleChanges.fullDatasource.currentValue : [];
            this.fullDatasource = FlatTreeService.convertTreeToFlatTree(currentSource, this.treeConfig);
            this.filterDatasource = this.fullDatasource;
            this.setDataSourceOrigin();
        }
        if ('treeConfig' in simpleChanges) {
            this.treeConfig = simpleChanges.treeConfig.currentValue;
            if (this.treeConfig) {
                this.fullDatasource = FlatTreeService.convertTreeToFlatTree(this.fullDatasource, this.treeConfig);
                this.filterDatasource = this.fullDatasource;
                this.setDataSourceOrigin();
            }
        }
        if ('multiple' in simpleChanges) {
            this.multiple = simpleChanges.multiple.currentValue;
            if (!this.multiple) {
                this.isHideCheckbox = true;
            }
        }
        if ('disabled' in simpleChanges) {
            this.disabled = simpleChanges.disabled.currentValue;
            if (this.disabled !== undefined && this.disabled !== null) {
                if (!this.treeConfig) {
                    this.treeConfig = new FlatTreeConfigModel();
                }
                this.treeConfig.disabled = this.disabled;
                this.fullDatasource = FlatTreeService.convertTreeToFlatTree(this.fullDatasource, this.treeConfig);
                this.filterDatasource = this.fullDatasource;
                this.setDataSourceOrigin();
            }
        }
        if ('searchTextOutSide' in simpleChanges) {
            this.searchText = simpleChanges.searchTextOutSide.currentValue ? simpleChanges.searchTextOutSide.currentValue : '';
            this.onChangeSearchText();
        }
        if (this.value) {
            this.writeValue(this.value);
        }
    }
    transformer = (node, level) => {
        node.expandable = FlatTreeService.hasChild(node);
        node.level = level;
        node.checked = !!node.checked;
        return node;
    };
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    registerOnChange(fn) {
        this.propagateChange(fn);
    }
    registerOnTouched(fn) {
        this.propagateChange(fn);
    }
    writeValue(obj) {
        // if (this.multiple && !obj) {
        //   obj = [];
        // }
        if (obj) {
            // if (this.multiple) {
            this.value = obj;
            // }
            this.mapIndexes = new Map();
            for (let i = 0; i < this.fullDataTreeControl.dataNodes.length; i++) {
                this.mapIndexes.set(this.fullDataTreeControl.dataNodes[i].value, i);
            }
            this.checkedDefaultValue();
            this.updateSelectAll();
            this.expandTreeDataSource(this.treeControl, 'isExpanded');
            this.updateSelectedTree();
            this.callValidator();
            if (this.isView) {
                this.selectedTreeControl.expandAll();
            }
            this.selectionChange.emit(Array.from(this.valueObjRef.values()));
        }
    }
    updateSelectedTree() {
        this.selectedFullDataSource = [];
        this.getCheckedSelectedTreeDataSource(this.fullDataDataSource.data, this.selectedFullDataSource);
        this.setSelectedNode();
        this.expandTreeDataSource(this.selectedTreeControl, 'isExpanded');
    }
    checkedDefaultValue() {
        this.valueObjRef.clear();
        const valueSet = new Set(this.value);
        for (const node of this.fullDataTreeControl.dataNodes) {
            const isLeaf = !FlatTreeService.hasChild(node);
            node.checked = isLeaf && valueSet.has(node.value);
            if (isLeaf && node.checked) {
                this.valueObjRef.set(node.value, node);
            }
            const orgNodeIndex = this.mapIndexes.get(node.value);
            if (orgNodeIndex !== undefined) {
                this.fullDataTreeControl.dataNodes[orgNodeIndex].checked = node.checked;
            }
        }
    }
    getAllChildNode(treeControl, node) {
        const index = this.mapIndexes.get(node.value);
        let sameLevelNextIndex = -1;
        for (let i = index + 1; i < treeControl.dataNodes.length; i++) {
            if (node.level >= treeControl.dataNodes[i].level) {
                sameLevelNextIndex = i;
                break;
            }
        }
        return treeControl.dataNodes.slice(index + 1, sameLevelNextIndex < 0 ? treeControl.dataNodes.length : sameLevelNextIndex);
    }
    updateSelectAll(childrenNode) {
        const data = childrenNode ? childrenNode : this.dataSource.data;
        data.forEach(node => {
            if (FlatTreeService.hasChild(node)) {
                this.updateSelectAll(node.children);
                node.checked = !!node.children && node.children.reduce((checkAll, curChildNode) => {
                    return checkAll && !!curChildNode.checked;
                }, true);
            }
        });
    }
    checkParentNode(checked, node, isSelectedChange) {
        node.checked = checked;
        let indexLeaf = -1;
        // update origin node
        let orgNodeIndex = this.mapIndexes.get(node.value);
        /*this.getNodeInFullDataSource(child)*/
        this.fullDataTreeControl.dataNodes[orgNodeIndex].checked = checked;
        if (orgNodeIndex > -1 && !checked) {
            this.fullDataTreeControl.dataNodes[orgNodeIndex].isExpanded = false;
        }
        const allChild = this.getAllChildNode(this.fullDataTreeControl, node); /*this.treeControl.getDescendants(node);*/
        allChild.reverse();
        allChild.forEach(child => {
            if (!FlatTreeService.hasChild(child)) {
                indexLeaf = this.value.indexOf(child.value);
                if (checked) {
                    if (indexLeaf < 0 && !child.disabled && child.display) {
                        child.checked = checked;
                        this.value.push(child.value);
                        this.valueObjRef.set(child.value, child);
                    }
                }
                else {
                    if ((indexLeaf >= 0 && !child.disabled && child.display) || !!isSelectedChange) {
                        child.checked = checked;
                        this.value.splice(indexLeaf, 1);
                        this.valueObjRef.delete(child.value);
                    }
                }
            }
            else {
                orgNodeIndex = this.mapIndexes.get(child.value);
                if (orgNodeIndex > -1) {
                    this.fullDataTreeControl.dataNodes[orgNodeIndex].isExpanded = false;
                    this.fullDataTreeControl.dataNodes[orgNodeIndex].checked = this.fullDataTreeControl.dataNodes[orgNodeIndex].children?.every(n => n.checked);
                }
            }
        });
        if (Array.isArray(this.value) && this.value.length === 0) {
            this.selectedTreeChange(node);
        }
        this.writeValue(this.value);
        this.cdr.detectChanges();
    }
    selectedTreeChange(node) {
        let checkExistSelected;
        if (node.level < 1) {
            checkExistSelected = this.selectedFullValues.has(node.value);
            if (node.checked) {
                this.selectedFullValues.set(node.value, node.value);
            }
            else if (!node.checked && checkExistSelected) {
                this.selectedFullValues.delete(node.value);
            }
            if (node.checked) {
                this.selectedTreeControl.expandDescendants(node);
            }
        }
        else {
            const rootNode = this.getRootNode(node);
            if (rootNode) {
                checkExistSelected = this.selectedFullValues.has(rootNode.value);
                if (node.checked) {
                    this.selectedFullValues.set(rootNode.value, rootNode.value);
                }
                else if (!node.checked && checkExistSelected) {
                    if (!this.getAllChildNode(this.fullDataTreeControl, rootNode) /*this.treeControl.getDescendants(rootNode)*/.some(child => child.checked)) {
                        this.selectedFullValues.delete(node.value);
                    }
                }
                if (rootNode.checked) {
                    this.selectedTreeControl.expandDescendants(rootNode);
                }
            }
        }
    }
    checkLeafNode(checked, node, isSelectedChange) {
        if ((node.display && !this.checkDisabledNode(node)) || !!isSelectedChange) {
            node.checked = checked;
            // update origin node
            const orgNodeIndex = this.mapIndexes.get(node.value);
            this.fullDataTreeControl.dataNodes[orgNodeIndex].checked = checked;
            if (checked) {
                if (this.multiple) {
                    if (!this.value.includes(node.value)) {
                        this.value.push(node.value);
                        this.valueObjRef.set(node.value, node);
                    }
                }
                else {
                    this.value = [node.value];
                    this.valueObjRef = new Map().set(node.value, node);
                }
            }
            else {
                this.value.splice(this.value.indexOf(node.value), 1);
                this.valueObjRef.delete(node.value);
            }
            if (Array.isArray(this.value) && this.value.length === 0) {
                this.selectedTreeChange(node);
            }
            this.writeValue(this.value);
            this.cdr.detectChanges();
        }
    }
    /* Get the parent node of a node */
    getRootNode(node) {
        const currentLevel = this._getLevel(node);
        if (currentLevel < 1) {
            return node;
        }
        const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;
        for (let i = startIndex; i >= 0; i--) {
            const currentNode = this.treeControl.dataNodes[i];
            if (this._getLevel(currentNode) < currentLevel) {
                return this.getRootNode(currentNode);
            }
        }
        return node;
    }
    deSelect(node) {
        this.checkLeafNode(false, node, true);
    }
    deSelectParent(node) {
        this.checkParentNode(false, node, true);
    }
    toggleTreeControl(treeControl, node) {
        treeControl.toggle(node);
        const orgNode = this.fullDataTreeControl.dataNodes.find(n => n.value === node.value);
        if (orgNode) {
            orgNode.isFilterExpanded = treeControl.isExpanded(node);
        }
        this.setDataSourceOrigin();
    }
    toggleSelectedTree(node) {
        if (node) {
            this.selectedTreeControl.toggle(node);
            const orgNode = this.fullDataTreeControl.dataNodes.find(n => n.value === node.value);
            if (orgNode) {
                orgNode.isExpanded = this.selectedTreeControl.isExpanded(node);
            }
            if (this.selectedVirtualScroll) {
                this.selectedVirtualScroll.checkViewportSize();
            }
        }
        else {
            this.isCollapseSelected = !this.isCollapseSelected;
        }
    }
    onChangeSearchText() {
        this.filterDatasource = [];
        this.getDisplayTreeDataSource(this.fullDataDataSource.data, this.filterDatasource);
        this.setDataSourceOrigin();
        this.expandTreeDataSource(this.treeControl, 'isFilterExpanded');
        if (this.chooseVirtualScroll) {
            this.chooseVirtualScroll.scrollToIndex(0);
        }
    }
    getDisplayTreeDataSource(dataOrigin, copiedData) {
        if (!Array.isArray(dataOrigin)) {
            return [];
        }
        let copiedNode;
        for (const node of dataOrigin) {
            copiedNode = {
                ...node,
                children: [],
            };
            if (!node.children || !FlatTreeService.hasChild(node)) {
                node.display = node.displayValue.toLowerCase().includes(this.searchText.toLowerCase())
                    && this.getDisplayInputFunc(node);
                if (node.display) {
                    copiedData.push(node);
                }
            }
            else {
                this.getDisplayTreeDataSource(node.children, copiedNode.children ? copiedNode.children : []);
                // parent display
                node.display = (node.displayValue.toLowerCase().includes(this.searchText.toLowerCase())
                    || node.children?.some(childNode => childNode.display)) && this.getDisplayInputFunc(node);
                node.checked = node.children.filter(child => child.display).length > 0 &&
                    node.children.filter(child => child.display).every(childNode => childNode.checked);
                copiedNode.display = node.display;
                copiedNode.checked = node.checked;
                if (node.display) {
                    if (!this.getAllChildNode(this.fullDataTreeControl, node).some(childNode => childNode.display)) {
                        this.getAllChildNode(this.fullDataTreeControl, node).forEach(childNode => childNode.display = true);
                        copiedData.push(node);
                    }
                    else {
                        copiedData.push(copiedNode);
                    }
                }
            }
        }
    }
    getCheckedSelectedTreeDataSource(dataOrigin, copiedData) {
        if (!Array.isArray(dataOrigin)) {
            return [];
        }
        let copiedNode;
        for (const node of dataOrigin) {
            copiedNode = {
                ...node,
                children: [],
            };
            if (!node.children || (Array.isArray(node.children) && node.children.length === 0)) {
                if (node.checked) {
                    copiedData.push(node);
                }
            }
            else {
                this.getCheckedSelectedTreeDataSource(node.children, copiedNode.children ? copiedNode.children : []);
                // parent checked
                node.checked = this.getAllChildNode(this.fullDataTreeControl, node).every(childNode => childNode.checked);
                node.checkedDisplay = node.checked || this.getAllChildNode(this.fullDataTreeControl, node).some(childNode => childNode.checked);
                copiedNode.checkedDisplay = node.checkedDisplay;
                if (node.checkedDisplay) {
                    if (!this.getAllChildNode(this.fullDataTreeControl, node).some(childNode => childNode.checked)) {
                        this.getAllChildNode(this.fullDataTreeControl, node).forEach(childNode => childNode.checked = true);
                        copiedData.push(node);
                    }
                    else {
                        copiedData.push(copiedNode);
                    }
                }
            }
        }
    }
    expandTreeDataSource(treeControl, expandProperty) {
        treeControl.dataNodes.filter(n => treeControl.isExpandable(n))
            .forEach(child => {
            if (child[expandProperty]) {
                treeControl.expand(child);
            }
            else {
                treeControl.collapse(child);
            }
        });
    }
    onLeafNodeClick(node) {
        this.nodeClicked = node;
        this.onNodeClick.emit(node);
        if (this.isHideCheckbox) {
            this.value = [];
            this.valueObjRef.clear();
            this.checkLeafNode(true, node);
        }
    }
    onParentNodeClick(node) {
        this.nodeClicked = node;
        this.onNodeClick.emit(node);
        if (this.isHideCheckbox) {
            this.value = [];
            this.valueObjRef.clear();
            this.checkParentNode(true, node);
        }
    }
    toggleNodeCheck(node, checked) {
        const isLeaf = !FlatTreeService.hasChild(node);
        // Gọi 1 lần duy nhất nếu là parent
        const descendants = isLeaf ? [] : this.fullDataTreeControl.getDescendants(node);
        const affectedNodes = isLeaf ? [node] : descendants.filter(n => !FlatTreeService.hasChild(n));
        for (const leaf of affectedNodes) {
            if (!leaf.display || this.checkDisabledNode(leaf))
                continue;
            const index = this.value.indexOf(leaf.value);
            if (checked && index < 0) {
                this.value.push(leaf.value);
                this.valueObjRef.set(leaf.value, leaf);
                leaf.checked = true;
            }
            if (!checked && index >= 0) {
                this.value.splice(index, 1);
                this.valueObjRef.delete(leaf.value);
                leaf.checked = false;
            }
            const orgNodeIndex = this.mapIndexes.get(leaf.value);
            if (orgNodeIndex !== undefined) {
                this.fullDataTreeControl.dataNodes[orgNodeIndex].checked = leaf.checked;
            }
        }
        // Nếu node là cha → cập nhật isExpanded
        if (!isLeaf) {
            node.checked = checked;
            const orgNodeIndex = this.mapIndexes.get(node.value);
            if (orgNodeIndex !== undefined) {
                this.fullDataTreeControl.dataNodes[orgNodeIndex].checked = checked;
                this.fullDataTreeControl.dataNodes[orgNodeIndex].isExpanded = false;
            }
        }
        else {
            node.checked = checked;
        }
        this.writeValue(this.value);
        this.cdr.detectChanges();
    }
    _getLevel = (node) => node.level;
    _isExpandable = (node) => FlatTreeService.hasChild(node);
    _getChildren = (node) => of(node.children ? node.children : []);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaFlatTreeComponent, deps: [{ token: i1.TranslateService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaFlatTreeComponent, isStandalone: false, selector: "cva-flat-tree", inputs: { label: "label", required: "required", value: "value", multiple: "multiple", disabled: "disabled", isView: "isView", isDisplayChooseTreeOnly: "isDisplayChooseTreeOnly", isHideCheckbox: "isHideCheckbox", isCollapseSelected: "isCollapseSelected", selectedLabelTitle: "selectedLabelTitle", viewHeight: "viewHeight", itemSize: "itemSize", percentOfLabelOutside: "percentOfLabelOutside", treeConfig: "treeConfig", isSearchOutSide: "isSearchOutSide", searchTextOutSide: "searchTextOutSide", errorMessages: "errorMessages", fullDatasource: "fullDatasource", isFormControl: "isFormControl" }, outputs: { selectionChange: "selectionChange", onNodeClick: "onNodeClick" }, viewQueries: [{ propertyName: "chooseVirtualScroll", first: true, predicate: ["chooseAreaScrollViewport"], descendants: true }, { propertyName: "selectedVirtualScroll", first: true, predicate: ["selectedScrollViewport"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
    <div class="cva-flat-tree labelOutside"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="label && !isSearchOutSide" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : '') | translate }}<span class="required-label-outside">{{ required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <div class="tree-area"
           fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div fxLayout="row wrap">
          <div class="choose-area"
               *ngIf="!checkIsView(isView) && !isCollapseSelected"
               fxLayout="column" fxFlex="1 1 {{isDisplayChooseTreeOnly ? '100%' : '50%'}}" fxFlex.lt-sm="100%">
            <div class="header-choose-area">
              <div class="title-choose-tree" fxLayout="row" fxLayout.lt-sm="row wrap">
                <mat-label fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%" class="label_width"
                           *ngIf="label && isSearchOutSide">
                  <div class="label">{{ (label ? label : '') | translate }}<span
                    class="required-label-outside">{{ required ? '*' : '' }}</span></div>
                </mat-label>
                <mat-divider *ngIf="label && isSearchOutSide"></mat-divider>
              </div>
              <mat-form-field appearance="outline"
                              *ngIf="!isSearchOutSide"
                              fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
                <input matInput
                       placeholder="{{'common.searchText'|translate}}"
                       [(ngModel)]="searchText"
                       (ngModelChange)="onChangeSearchText()"
                       autocomplete="off">
              </mat-form-field>
            </div>
            <cdk-virtual-scroll-viewport #chooseAreaScrollViewport itemSize="{{itemSize}}"
                                         [ngStyle]="{height: viewHeight + 'px'}">
              <ng-container *cdkVirtualFor="let node of dataSource">
                <cva-flat-tree-node-left
                  [ngStyle]="{height: itemSize + 'px', padding: '0px 0px 0px '+ (node.level * paddingLeft) +'px'}"
                  [attr.aria-level]="node.level"
                  [treeControl]="treeControl"
                  [isHideCheckbox]="isHideCheckbox"
                  [nodeClicked]="nodeClicked"
                  [node]="node"
                  (toggle)="toggleTreeControl(treeControl, node)"
                  (onParentNodeClick)="onParentNodeClick(node)"
                  (onLeafNodeClick)="onLeafNodeClick(node)"
                  (ngModelParentChange)="toggleNodeCheck(node, $event)"
                  (ngModelLeafChange)="toggleNodeCheck(node, $event)">
                </cva-flat-tree-node-left>
              </ng-container>
            </cdk-virtual-scroll-viewport>
          </div>
          <div class="selected-area {{isCollapseSelected ? 'hiddenTree' : ''}}"
               *ngIf="!isDisplayChooseTreeOnly"
               fxLayout="column" fxFlex="1 1 {{checkIsView(isView) ? '100%' : '50%'}}" fxFlex.lt-sm="100%">
            <div class="header-area" *ngIf="!isView">
              <label>{{ selectedLabelTitle | translate }}{{ '(' + (value ? value.length : 0) + ')' }}</label>
              <div class="collapse-expand-all" (click)="toggleSelectedTree()">
                {{ (isCollapseSelected ? 'common.selected.tree.expandAll' : 'common.selected.tree.collapse') | translate }}
                <i class="fa {{isCollapseSelected ? 'fa-chevron-down' : 'fa-chevron-up'}}"></i>
              </div>
            </div>
            <cdk-virtual-scroll-viewport #selectedScrollViewport
                                         *ngIf="!isCollapseSelected"
                                         itemSize="{{itemSize}}" [ngStyle]="{height: viewHeight + 'px'}">
              <ng-container *cdkVirtualFor="let node of selectedDataSource">
                <cva-flat-tree-node-right
                  [ngStyle]="{height: itemSize + 'px', padding: '0px 0px 0px '+ (node.level * paddingLeft) +'px'}"
                  [attr.aria-level]="node.level"
                  [treeControl]="selectedTreeControl"
                  [node]="node"
                  [isView]="isView"
                  (toggle)="toggleSelectedTree(node)"
                  (deSelectLeafNode)="deSelect(node)"
                  (deSelectParentNode)="deSelectParent(node)">
                </cva-flat-tree-node-right>
              </ng-container>
            </cdk-virtual-scroll-viewport>
          </div>
        </div>
        <mat-hint *ngIf="NsValiator.invalid(formControl)">
          {{ NsValiator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </div>
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl],      input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i6$2.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i10.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i10.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i10.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultStyleDirective, selector: "  [ngStyle],  [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl],  [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl],  [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { kind: "component", type: CvaFlatTreeNodeLeftComponent, selector: "cva-flat-tree-node-left", inputs: ["treeControl", "isHideCheckbox", "node", "nodeClicked"], outputs: ["toggle", "onParentNodeClick", "onLeafNodeClick", "ngModelParentChange", "ngModelLeafChange"] }, { kind: "component", type: CvaFlatTreeNodeRightComponent, selector: "cva-flat-tree-node-right", inputs: ["treeControl", "node", "isView"], outputs: ["toggle", "deSelectLeafNode", "deSelectParentNode"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaFlatTreeComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'cva-flat-tree',
                    standalone: false,
                    template: `
    <div class="cva-flat-tree labelOutside"
         fxLayout="row" fxLayout.lt-sm="row wrap">
      <mat-label *ngIf="label && !isSearchOutSide" class="label_width"
                 fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div class="label">
          <div>
            {{ (label ? label : '') | translate }}<span class="required-label-outside">{{ required ? '*' : '' }}</span>
          </div>
        </div>
      </mat-label>
      <div class="tree-area"
           fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
        <div fxLayout="row wrap">
          <div class="choose-area"
               *ngIf="!checkIsView(isView) && !isCollapseSelected"
               fxLayout="column" fxFlex="1 1 {{isDisplayChooseTreeOnly ? '100%' : '50%'}}" fxFlex.lt-sm="100%">
            <div class="header-choose-area">
              <div class="title-choose-tree" fxLayout="row" fxLayout.lt-sm="row wrap">
                <mat-label fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%" class="label_width"
                           *ngIf="label && isSearchOutSide">
                  <div class="label">{{ (label ? label : '') | translate }}<span
                    class="required-label-outside">{{ required ? '*' : '' }}</span></div>
                </mat-label>
                <mat-divider *ngIf="label && isSearchOutSide"></mat-divider>
              </div>
              <mat-form-field appearance="outline"
                              *ngIf="!isSearchOutSide"
                              fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
                <input matInput
                       placeholder="{{'common.searchText'|translate}}"
                       [(ngModel)]="searchText"
                       (ngModelChange)="onChangeSearchText()"
                       autocomplete="off">
              </mat-form-field>
            </div>
            <cdk-virtual-scroll-viewport #chooseAreaScrollViewport itemSize="{{itemSize}}"
                                         [ngStyle]="{height: viewHeight + 'px'}">
              <ng-container *cdkVirtualFor="let node of dataSource">
                <cva-flat-tree-node-left
                  [ngStyle]="{height: itemSize + 'px', padding: '0px 0px 0px '+ (node.level * paddingLeft) +'px'}"
                  [attr.aria-level]="node.level"
                  [treeControl]="treeControl"
                  [isHideCheckbox]="isHideCheckbox"
                  [nodeClicked]="nodeClicked"
                  [node]="node"
                  (toggle)="toggleTreeControl(treeControl, node)"
                  (onParentNodeClick)="onParentNodeClick(node)"
                  (onLeafNodeClick)="onLeafNodeClick(node)"
                  (ngModelParentChange)="toggleNodeCheck(node, $event)"
                  (ngModelLeafChange)="toggleNodeCheck(node, $event)">
                </cva-flat-tree-node-left>
              </ng-container>
            </cdk-virtual-scroll-viewport>
          </div>
          <div class="selected-area {{isCollapseSelected ? 'hiddenTree' : ''}}"
               *ngIf="!isDisplayChooseTreeOnly"
               fxLayout="column" fxFlex="1 1 {{checkIsView(isView) ? '100%' : '50%'}}" fxFlex.lt-sm="100%">
            <div class="header-area" *ngIf="!isView">
              <label>{{ selectedLabelTitle | translate }}{{ '(' + (value ? value.length : 0) + ')' }}</label>
              <div class="collapse-expand-all" (click)="toggleSelectedTree()">
                {{ (isCollapseSelected ? 'common.selected.tree.expandAll' : 'common.selected.tree.collapse') | translate }}
                <i class="fa {{isCollapseSelected ? 'fa-chevron-down' : 'fa-chevron-up'}}"></i>
              </div>
            </div>
            <cdk-virtual-scroll-viewport #selectedScrollViewport
                                         *ngIf="!isCollapseSelected"
                                         itemSize="{{itemSize}}" [ngStyle]="{height: viewHeight + 'px'}">
              <ng-container *cdkVirtualFor="let node of selectedDataSource">
                <cva-flat-tree-node-right
                  [ngStyle]="{height: itemSize + 'px', padding: '0px 0px 0px '+ (node.level * paddingLeft) +'px'}"
                  [attr.aria-level]="node.level"
                  [treeControl]="selectedTreeControl"
                  [node]="node"
                  [isView]="isView"
                  (toggle)="toggleSelectedTree(node)"
                  (deSelectLeafNode)="deSelect(node)"
                  (deSelectParentNode)="deSelectParent(node)">
                </cva-flat-tree-node-right>
              </ng-container>
            </cdk-virtual-scroll-viewport>
          </div>
        </div>
        <mat-hint *ngIf="NsValiator.invalid(formControl)">
          {{ NsValiator.getErrorMessage(formControl, errorMessages) | translate }}
        </mat-hint>
      </div>
    </div>
  `,
                }]
        }], ctorParameters: () => [{ type: i1.TranslateService }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { label: [{
                type: Input
            }], required: [{
                type: Input
            }], value: [{
                type: Input
            }], multiple: [{
                type: Input
            }], disabled: [{
                type: Input
            }], isView: [{
                type: Input
            }], isDisplayChooseTreeOnly: [{
                type: Input
            }], isHideCheckbox: [{
                type: Input
            }], isCollapseSelected: [{
                type: Input
            }], selectedLabelTitle: [{
                type: Input
            }], viewHeight: [{
                type: Input
            }], itemSize: [{
                type: Input
            }], percentOfLabelOutside: [{
                type: Input
            }], treeConfig: [{
                type: Input
            }], isSearchOutSide: [{
                type: Input
            }], searchTextOutSide: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], fullDatasource: [{
                type: Input
            }], selectionChange: [{
                type: Output
            }], onNodeClick: [{
                type: Output
            }], isFormControl: [{
                type: Input
            }], chooseVirtualScroll: [{
                type: ViewChild,
                args: ['chooseAreaScrollViewport', { static: false }]
            }], selectedVirtualScroll: [{
                type: ViewChild,
                args: ['selectedScrollViewport', { static: false }]
            }] } });

class CvaDialogImportFileComponent {
    matDialogRef;
    apiService;
    utilsService;
    translateService;
    data;
    file;
    errorImportExcelUrl = '';
    inputFileRef;
    constructor(matDialogRef, apiService, utilsService, translateService, data) {
        this.matDialogRef = matDialogRef;
        this.apiService = apiService;
        this.utilsService = utilsService;
        this.translateService = translateService;
        this.data = data;
    }
    ngOnInit() {
    }
    onDropped(fileList) {
        this.handleFile(fileList);
    }
    onFileChange(event, inputRef) {
        const files = event.target.files;
        this.handleFile(files);
    }
    downloadTemplate() {
        if (this.data.downloadTemplateFunc)
            this.data.downloadTemplateFunc();
    }
    onClickChooseFile(inputFile) {
        inputFile.click();
    }
    close() {
        this.matDialogRef.close();
    }
    onImport() {
        this.utilsService.showConfirmDialog(this.data.confirmMsgKey, [])
            .afterClosed().subscribe((value) => {
            if (value.value) {
                if (this.data.importFunc) {
                    this.data.importFunc(this.file).subscribe((data) => {
                        if (data) {
                            this.utilsService.onSuccessFunc(this.data.successMsgKey);
                            this.matDialogRef.close({ done: true, kpis: data });
                        }
                    }, errorExcelUrl => {
                        this.utilsService.showErrorToarst(this.data.errorMsgKey);
                        this.errorImportExcelUrl = errorExcelUrl;
                        if (this.inputFileRef) {
                            this.inputFileRef.nativeElement.value = '';
                        }
                        this.file = undefined;
                    });
                }
            }
        });
    }
    downloadErrorFile() {
        if (this.data.downloadErrorFile) {
            this.data.downloadErrorFile(this.errorImportExcelUrl);
        }
        else {
            this.onDownloadErrorFile();
        }
    }
    onDownloadErrorFile() {
        this.apiService.saveFile('/files/' + this.errorImportExcelUrl, null, {});
    }
    handleFile(files) {
        if (files && files.length) {
            const file = files[0];
            const af = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel'];
            if (file.type === af[0]) {
                this.file = file;
            }
            else {
                this.translateService.get("common.only.allow.excel")
                    .subscribe(msg => {
                    this.utilsService.showWarningToarst(msg);
                });
            }
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaDialogImportFileComponent, deps: [{ token: i1$1.MatDialogRef }, { token: ApiService }, { token: UtilsService }, { token: i1.TranslateService }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaDialogImportFileComponent, isStandalone: false, selector: "cva-dialog-import-file", viewQueries: [{ propertyName: "inputFileRef", first: true, predicate: ["inputFile"], descendants: true }], ngImport: i0, template: `
        <div>
            <h2>{{'common.import.excel.' | translate}}</h2>
            <div appDragDrop class="areaImportFile" (onFileDropped)="onDropped($event)"
                 (click)="onClickChooseFile(inputFile)">
                <input class="d-zone" type="file"
                       #inputFile
                       (change)="onFileChange($event, inputFile)">
                <span>
          <i class="fal fa-plus mr-2"></i> {{'common.import.excel.drag.drop' | translate}}
        </span>
            </div>
            <h4 style="width: 26rem">
                {{file?.name}}
            </h4>
            <div class="but">
                <button mat-button (click)="close()" type="button" class="primary outline">
                    {{'btnCancel' | translate}}
                </button>
                <button mat-button type="button" (click)="onImport()" class="primary">
                    {{'btnImport' | translate}}
                </button>
                <button mat-button *ngIf="errorImportExcelUrl" (click)="downloadErrorFile()" type="button"
                        class="danger">
                    {{'common.import.excel.download.error.file' | translate}}
                </button>
            </div>

            <div class="download-template"><p>{{'common.import.excel.not.have.template' | translate}}</p><span
                    (click)="downloadTemplate()">{{'common.import.excel.download.template' | translate}}</span></div>
        </div>    `, isInline: true, styles: [":host{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:0!important}h2,h4{margin:2rem;text-align:center}p{display:inline;text-align:center}span{color:#36f;cursor:pointer;text-align:center}.d-zone{display:none}.areaImportFile{width:26rem;height:10rem;border:1px dashed #3366FF;background:#fff!important;box-sizing:border-box;border-radius:10px;display:flex;justify-content:center;align-items:center;margin:2rem;cursor:pointer}.but{margin:2rem;display:flex;justify-content:center}.download-template{display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: "    button[mat-button], button[mat-raised-button], button[mat-flat-button],    button[mat-stroked-button]  ", exportAs: ["matButton"] }, { kind: "directive", type: DragDropDirective, selector: "[appDragDrop]", outputs: ["onFileDropped"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaDialogImportFileComponent, decorators: [{
            type: Component,
            args: [{ selector: 'cva-dialog-import-file', standalone: false, template: `
        <div>
            <h2>{{'common.import.excel.' | translate}}</h2>
            <div appDragDrop class="areaImportFile" (onFileDropped)="onDropped($event)"
                 (click)="onClickChooseFile(inputFile)">
                <input class="d-zone" type="file"
                       #inputFile
                       (change)="onFileChange($event, inputFile)">
                <span>
          <i class="fal fa-plus mr-2"></i> {{'common.import.excel.drag.drop' | translate}}
        </span>
            </div>
            <h4 style="width: 26rem">
                {{file?.name}}
            </h4>
            <div class="but">
                <button mat-button (click)="close()" type="button" class="primary outline">
                    {{'btnCancel' | translate}}
                </button>
                <button mat-button type="button" (click)="onImport()" class="primary">
                    {{'btnImport' | translate}}
                </button>
                <button mat-button *ngIf="errorImportExcelUrl" (click)="downloadErrorFile()" type="button"
                        class="danger">
                    {{'common.import.excel.download.error.file' | translate}}
                </button>
            </div>

            <div class="download-template"><p>{{'common.import.excel.not.have.template' | translate}}</p><span
                    (click)="downloadTemplate()">{{'common.import.excel.download.template' | translate}}</span></div>
        </div>    `, styles: [":host{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:0!important}h2,h4{margin:2rem;text-align:center}p{display:inline;text-align:center}span{color:#36f;cursor:pointer;text-align:center}.d-zone{display:none}.areaImportFile{width:26rem;height:10rem;border:1px dashed #3366FF;background:#fff!important;box-sizing:border-box;border-radius:10px;display:flex;justify-content:center;align-items:center;margin:2rem;cursor:pointer}.but{margin:2rem;display:flex;justify-content:center}.download-template{display:flex;justify-content:center;align-items:center}\n"] }]
        }], ctorParameters: () => [{ type: i1$1.MatDialogRef }, { type: ApiService }, { type: UtilsService }, { type: i1.TranslateService }, { type: DialogImportFileConfigModel, decorators: [{
                    type: Inject,
                    args: [MAT_DIALOG_DATA]
                }] }], propDecorators: { inputFileRef: [{
                type: ViewChild,
                args: ['inputFile', { static: false }]
            }] } });

class CvaQuillEditorComponent {
    injector;
    label = '';
    name = '';
    placeholder = '';
    hint = '';
    required = false;
    disabled = false;
    text = '';
    textCounter = 0;
    quillStyle;
    // nếu cho vào base thì define rõ ràng, default check valid only text
    quillModule = undefined;
    onlyCheckTextValidation = true;
    format = 'html';
    pattern = null;
    readonly = false;
    errorMessages = new Map();
    onChange = new EventEmitter();
    multiline = false;
    isLabelOutside = false;
    isFloatLabel = true;
    minLength;
    maxLength;
    maxSize; // don vi byte
    minSize; // don vi byte
    onFocusStatus = false;
    /* hiển thị suffix thay maxlength */
    maxLengthDisplay;
    // Chỉ bằng false khi trong NsSmartTable thôi nhé @@
    isFormControl = true;
    formatFunc;
    control = undefined;
    get NsValidator() {
        return ValidatorService;
    }
    constructor(injector, ngControl) {
        this.injector = injector;
        if (ngControl) {
            // Hành động này thay cho provide: NG_VALUE_ACCESSOR và gắn ControlValueAccessor này vào parent FormControl
            ngControl.valueAccessor = this;
        }
    }
    ngOnInit() {
        this.callValidator();
    }
    get textValue() {
        return this.text;
    }
    set textValue(val) {
        this.writeValue(val);
    }
    customLengthValidator = (control) => {
        let length = 0;
        if (!this.onlyCheckTextValidation) {
            const description = control?.value ? control?.value : '';
            length = new Blob([description]).size;
        }
        else {
            length = this.textCounter;
        }
        if (!!this.minLength && length < this.minLength) {
            return {
                minlength: {
                    min: this.minLength,
                    actual: length
                }
            };
        }
        if (!!this.maxLength && length > this.maxLength) {
            return {
                maxlength: {
                    max: this.maxLength,
                    actual: length
                }
            };
        }
        return null;
    };
    customSizeValidator = (control) => {
        let size = 0;
        const description = control?.value ? control?.value : '';
        size = new Blob([description]).size;
        if (!!this.minSize && size < this.minSize) {
            return {
                minsize: {
                    min: this.minSize,
                    actual: size
                }
            };
        }
        if (!!this.maxSize && size > this.maxSize) {
            return {
                maxsize: {
                    max: this.maxSize,
                    actual: size
                }
            };
        }
        return null;
    };
    callValidator() {
        const ngControl = this.injector.get(NgControl);
        // Nếu parent FormControl khởi tạo xong và formControl chưa có giá trị lưu
        if (ngControl && !this.control) {
            // Nếu là NsSmartTable thì phải tự new FormControl còn không thì cứ hóng parent FormControl về ^^
            if (this.isFormControl) {
                this.control = ngControl.control ? ngControl.control : undefined;
            }
            else {
                this.control = new FormControl();
            }
            // Hành động này gắn validator vào this.formControl
            // - Nếu this.formControl là parent FormControl thì sẽ show error lên FormGroup
            // - Nếu this.formControl là new FormControl thì sẽ quét QueryList để check {errors}
            if (this.control) {
                if (this.control.validator) {
                    this.control.setValidators([...ValidatorService.generateNsInputValidators({
                            required: this.required,
                            minLength: undefined,
                            maxLength: undefined,
                            pattern: this.pattern,
                        }), this.control.validator, this.customLengthValidator, this.customSizeValidator]);
                }
                else {
                    this.control.setValidators([...ValidatorService.generateNsInputValidators({
                            required: this.required,
                            minLength: undefined,
                            maxLength: undefined,
                            pattern: this.pattern,
                        }), this.customLengthValidator, this.customSizeValidator]);
                }
            }
        }
        if (this.control) {
            // Nếu this.formControl thuộc NsSmartTable thì setValue lại
            if (!this.isFormControl) {
                this.control.setValue(this.text);
            }
            // Nếu là parent FormControl rồi thì kệ
            this.control.updateValueAndValidity();
        }
    }
    propagateChange = (_) => {
        /*NON-EMPTY FOR COMPILE*/
    };
    /**
     * Write a new value to the element.
     */
    writeValue(obj) {
        this.text = obj;
        this.propagateChange(this.text);
        this.callValidator();
        this.onChange.emit(this.text);
    }
    /**
     * Set the function to be called
     * when the formControl receives a change event.
     */
    registerOnChange(fn) {
        this.propagateChange = fn;
    }
    /**
     * Set the function to be called
     * when the formControl receives a touch event.
     */
    registerOnTouched() {
        /*NON-EMPTY FOR COMPILE*/
    }
    displayLength() {
        if (this.maxLength === null || this.maxLength === undefined) {
            return this.maxLengthDisplay ? this.maxLengthDisplay : '';
        }
        return (this.textValue?.length ? this.textValue.length : 0) + '/' + this.getMaxLength();
    }
    getMaxLength() {
        return this.maxLengthDisplay ? this.maxLengthDisplay : this.maxLength;
    }
    onFocus(event) {
        this.onFocusStatus = true;
    }
    onBlur(event) {
        if (this.onFocusStatus) {
            this.onFocusStatus = false;
        }
    }
    onChangeContent(quill, text) {
        if (!text.html) {
            this.textCounter = 0;
        }
        else {
            this.textCounter = quill.editorElem.innerText.length;
        }
        this.writeValue(this.text);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaQuillEditorComponent, deps: [{ token: i0.Injector }, { token: i1$2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: CvaQuillEditorComponent, isStandalone: false, selector: "cva-quill-editor", inputs: { label: "label", name: "name", placeholder: "placeholder", hint: "hint", required: "required", disabled: "disabled", text: "text", quillStyle: "quillStyle", quillModule: "quillModule", onlyCheckTextValidation: "onlyCheckTextValidation", format: "format", pattern: "pattern", readonly: "readonly", errorMessages: "errorMessages", multiline: "multiline", isLabelOutside: "isLabelOutside", isFloatLabel: "isFloatLabel", minLength: "minLength", maxLength: "maxLength", maxSize: "maxSize", minSize: "minSize", maxLengthDisplay: "maxLengthDisplay", isFormControl: "isFormControl", formatFunc: "formatFunc" }, outputs: { onChange: "onChange" }, ngImport: i0, template: `
        <!-- css labelOutside trong base.theme-->
        <div class="cva-quill-editor"
             [ngClass]="{'labelOutside': !!isLabelOutside,
            'float_label': !!isFloatLabel && !isLabelOutside,
            'text_area': !!this.multiline}"
             fxLayout="row" fxLayout.lt-sm="row wrap">
            <mat-label *ngIf="isLabelOutside" class="label_width"
                       fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
                <div class="label">
                    <div>
                        {{(label ? label : '') | translate}}<span
                            class="required-label-outside">{{!!required ? '*' : ''}}</span>
                    </div>
                </div>
            </mat-label>
            <div class="editor" fxLayout="column" fxFlex="100%">
                <quill-editor [(ngModel)]="textValue"
                              [modules]="quillModule"
                              [disabled]="disabled"
                              [readOnly]="readonly"
                              [maxLength]="maxLength"
                              [minLength]="minLength"
                              [placeholder]="placeholder | translate"
                              [format]="format"
                              (onFocus)="onFocus($event)"
                              (onBlur)="onBlur($event)"
                              #quill [ngStyle]="quillStyle"
                              (onContentChanged)="onChangeContent(quill, $event)"
                              fxFlex="100%" fxFlex.lt-md="100%"
                ></quill-editor>
                <div id="counter"
                     *ngIf="!(disabled || readonly) && onFocusStatus && !!maxLength">{{textCounter + '/' + maxLength}}</div>
                <mat-hint align="start" *ngIf="!NsValidator.invalid(control)">{{hint | translate}}</mat-hint>
                <mat-hint style="color: red" align="start" *ngIf="NsValidator.invalid(control)">
                    {{NsValidator.getErrorMessageV1(control, errorMessages).msg | translate: NsValidator.getErrorMessageV1(control, errorMessages).params}}
                </mat-hint>
            </div>
        </div>
    `, isInline: true, styles: [".cva-quill-editor{margin-bottom:1rem}.cva-quill-editor .required-label-outside{color:red}.cva-quill-editor .ql-container.ql-snow{height:100px;overflow-y:auto}.cva-quill-editor #counter{border:1px solid #ccc;border-width:0px 1px 1px 1px;color:#aaa;padding:5px 15px;text-align:right}.cva-quill-editor quill-editor{margin-bottom:0!important;word-break:break-word}\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.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i4$4.QuillEditorComponent, selector: "quill-editor" }, { kind: "directive", type: i8.DefaultLayoutDirective, selector: "  [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md],  [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md],  [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm],  [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i8.DefaultFlexDirective, selector: "  [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md],  [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md],  [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm],  [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i9.DefaultClassDirective, selector: "  [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl],  [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl],  [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "directive", type: i9.DefaultStyleDirective, selector: "  [ngStyle],  [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl],  [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl],  [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: CvaQuillEditorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'cva-quill-editor', standalone: false, template: `
        <!-- css labelOutside trong base.theme-->
        <div class="cva-quill-editor"
             [ngClass]="{'labelOutside': !!isLabelOutside,
            'float_label': !!isFloatLabel && !isLabelOutside,
            'text_area': !!this.multiline}"
             fxLayout="row" fxLayout.lt-sm="row wrap">
            <mat-label *ngIf="isLabelOutside" class="label_width"
                       fxLayout="column" fxFlex="auto" fxFlex.lt-md="100%">
                <div class="label">
                    <div>
                        {{(label ? label : '') | translate}}<span
                            class="required-label-outside">{{!!required ? '*' : ''}}</span>
                    </div>
                </div>
            </mat-label>
            <div class="editor" fxLayout="column" fxFlex="100%">
                <quill-editor [(ngModel)]="textValue"
                              [modules]="quillModule"
                              [disabled]="disabled"
                              [readOnly]="readonly"
                              [maxLength]="maxLength"
                              [minLength]="minLength"
                              [placeholder]="placeholder | translate"
                              [format]="format"
                              (onFocus)="onFocus($event)"
                              (onBlur)="onBlur($event)"
                              #quill [ngStyle]="quillStyle"
                              (onContentChanged)="onChangeContent(quill, $event)"
                              fxFlex="100%" fxFlex.lt-md="100%"
                ></quill-editor>
                <div id="counter"
                     *ngIf="!(disabled || readonly) && onFocusStatus && !!maxLength">{{textCounter + '/' + maxLength}}</div>
                <mat-hint align="start" *ngIf="!NsValidator.invalid(control)">{{hint | translate}}</mat-hint>
                <mat-hint style="color: red" align="start" *ngIf="NsValidator.invalid(control)">
                    {{NsValidator.getErrorMessageV1(control, errorMessages).msg | translate: NsValidator.getErrorMessageV1(control, errorMessages).params}}
                </mat-hint>
            </div>
        </div>
    `, encapsulation: ViewEncapsulation.None, styles: [".cva-quill-editor{margin-bottom:1rem}.cva-quill-editor .required-label-outside{color:red}.cva-quill-editor .ql-container.ql-snow{height:100px;overflow-y:auto}.cva-quill-editor #counter{border:1px solid #ccc;border-width:0px 1px 1px 1px;color:#aaa;padding:5px 15px;text-align:right}.cva-quill-editor quill-editor{margin-bottom:0!important;word-break:break-word}\n"] }]
        }], ctorParameters: () => [{ type: i0.Injector }, { type: i1$2.NgControl, decorators: [{
                    type: Self
                }, {
                    type: Optional
                }] }], propDecorators: { label: [{
                type: Input
            }], name: [{
                type: Input
            }], placeholder: [{
                type: Input
            }], hint: [{
                type: Input
            }], required: [{
                type: Input
            }], disabled: [{
                type: Input
            }], text: [{
                type: Input
            }], quillStyle: [{
                type: Input
            }], quillModule: [{
                type: Input
            }], onlyCheckTextValidation: [{
                type: Input
            }], format: [{
                type: Input
            }], pattern: [{
                type: Input
            }], readonly: [{
                type: Input
            }], errorMessages: [{
                type: Input
            }], onChange: [{
                type: Output
            }], multiline: [{
                type: Input
            }], isLabelOutside: [{
                type: Input
            }], isFloatLabel: [{
                type: Input
            }], minLength: [{
                type: Input
            }], maxLength: [{
                type: Input
            }], maxSize: [{
                type: Input
            }], minSize: [{
                type: Input
            }], maxLengthDisplay: [{
                type: Input
            }], isFormControl: [{
                type: Input
            }], formatFunc: [{
                type: Input
            }] } });

class JsogHttpInterceptor {
    jSog;
    constructor(jSog) {
        this.jSog = jSog;
    }
    intercept(request, next) {
        if (request.body && !(request.body instanceof FormData)) {
            request = request.clone({ body: this.jSog.serialize(request.body) });
        }
        return next.handle(request).pipe(map((event) => {
            if (!(event instanceof HttpResponse || HttpResponseBase.prototype.isPrototypeOf(event))) {
                return event;
            }
            let response = event;
            if (!response.body || typeof (response.body) !== 'object' || (response.body instanceof Blob)) {
                return response;
            }
            response = response.clone({ body: this.jSog.deserializeArray(response.body, BaseModel) });
            return response;
        }));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: JsogHttpInterceptor, deps: [{ token: i1$6.JsogService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: JsogHttpInterceptor, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: JsogHttpInterceptor, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i1$6.JsogService }] });

class LoaderInterceptor {
    loaderService;
    requests = [];
    constructor(loaderService) {
        this.loaderService = loaderService;
    }
    removeRequest(req) {
        const i = this.requests.indexOf(req);
        if (i >= 0) {
            this.requests.splice(i, 1);
        }
        this.loaderService.isLoading.next(this.requests.length > 0);
    }
    intercept(request, next) {
        if (!request.headers.get('is_image') && !request.headers.get('is_live_searching')) {
            this.requests.push(request);
            this.loaderService.isLoading.next(true);
        }
        else {
            request = request.clone({
                headers: request.headers.delete('is_image').delete('is_live_searching'),
            });
        }
        return next.handle(request).pipe(map((event) => {
            if (event instanceof HttpResponse) {
                this.removeRequest(request);
            }
            return event;
        }), catchError(err => {
            console.error('Error: ', err);
            this.removeRequest(request);
            return throwError(err);
        }), finalize(() => {
            this.removeRequest(request);
        }));
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LoaderInterceptor, deps: [{ token: LoaderService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LoaderInterceptor, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LoaderInterceptor, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: LoaderService }] });

class AuthoritiesResolverService {
    authoritiesService;
    injector;
    apiService;
    config;
    constructor(authoritiesService, injector, apiService) {
        this.authoritiesService = authoritiesService;
        this.injector = injector;
        this.apiService = apiService;
        this.config = injector.get(InjectTokenNextSolutionsConfig);
    }
    resolve(route, state) {
        return !!this.authoritiesService.me && !!this.authoritiesService.me.userAuthentication ? of(this.authoritiesService.me)
            : this.apiService.get('/user/me', new HttpParams(), this.config.BASE_AUTHORIZATION_URL);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AuthoritiesResolverService, deps: [{ token: AuthoritiesService }, { token: i0.Injector }, { token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AuthoritiesResolverService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AuthoritiesResolverService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: AuthoritiesService }, { type: i0.Injector }, { type: ApiService }] });

class SingletonTranslateService {
    currentLanguage = new BehaviorSubject('');
    currentLanguage$ = this.currentLanguage.asObservable();
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SingletonTranslateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SingletonTranslateService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SingletonTranslateService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

const MATERIAL_MODULES = [
    MatAutocompleteModule,
    MatButtonModule,
    MatButtonToggleModule,
    MatCardModule,
    MatChipsModule,
    MatCheckboxModule,
    MatDatepickerModule,
    MatTableModule,
    MatDialogModule,
    MatFormFieldModule,
    MatGridListModule,
    MatIconModule,
    MatInputModule,
    MatListModule,
    MatMenuModule,
    MatPaginatorModule,
    MatProgressBarModule,
    MatProgressSpinnerModule,
    MatRippleModule,
    MatSelectModule,
    MatSidenavModule,
    MatSliderModule,
    MatSlideToggleModule,
    MatSnackBarModule,
    MatSortModule,
    MatStepperModule,
    MatTabsModule,
    MatToolbarModule,
    MatTooltipModule,
    MatTreeModule,
    OverlayModule,
    PortalModule,
    BidiModule,
    A11yModule,
    MatCommonModule,
    ObserversModule,
    MatRadioModule,
    ScrollingModule,
    ScrollingModule$1,
    CdkTreeModule,
];
class AngularMaterialModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AngularMaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.5", ngImport: i0, type: AngularMaterialModule, imports: [MatAutocompleteModule,
            MatButtonModule,
            MatButtonToggleModule,
            MatCardModule,
            MatChipsModule,
            MatCheckboxModule,
            MatDatepickerModule,
            MatTableModule,
            MatDialogModule,
            MatFormFieldModule,
            MatGridListModule,
            MatIconModule,
            MatInputModule,
            MatListModule,
            MatMenuModule,
            MatPaginatorModule,
            MatProgressBarModule,
            MatProgressSpinnerModule,
            MatRippleModule,
            MatSelectModule,
            MatSidenavModule,
            MatSliderModule,
            MatSlideToggleModule,
            MatSnackBarModule,
            MatSortModule,
            MatStepperModule,
            MatTabsModule,
            MatToolbarModule,
            MatTooltipModule,
            MatTreeModule,
            OverlayModule,
            PortalModule,
            BidiModule,
            A11yModule,
            MatCommonModule,
            ObserversModule,
            MatRadioModule,
            ScrollingModule,
            ScrollingModule$1,
            CdkTreeModule], exports: [MatAutocompleteModule,
            MatButtonModule,
            MatButtonToggleModule,
            MatCardModule,
            MatChipsModule,
            MatCheckboxModule,
            MatDatepickerModule,
            MatTableModule,
            MatDialogModule,
            MatFormFieldModule,
            MatGridListModule,
            MatIconModule,
            MatInputModule,
            MatListModule,
            MatMenuModule,
            MatPaginatorModule,
            MatProgressBarModule,
            MatProgressSpinnerModule,
            MatRippleModule,
            MatSelectModule,
            MatSidenavModule,
            MatSliderModule,
            MatSlideToggleModule,
            MatSnackBarModule,
            MatSortModule,
            MatStepperModule,
            MatTabsModule,
            MatToolbarModule,
            MatTooltipModule,
            MatTreeModule,
            OverlayModule,
            PortalModule,
            BidiModule,
            A11yModule,
            MatCommonModule,
            ObserversModule,
            MatRadioModule,
            ScrollingModule,
            ScrollingModule$1,
            CdkTreeModule] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AngularMaterialModule, providers: [
            CdkTree,
            CdkTreeNode,
        ], imports: [MATERIAL_MODULES, MatAutocompleteModule,
            MatButtonModule,
            MatButtonToggleModule,
            MatCardModule,
            MatChipsModule,
            MatCheckboxModule,
            MatDatepickerModule,
            MatTableModule,
            MatDialogModule,
            MatFormFieldModule,
            MatGridListModule,
            MatIconModule,
            MatInputModule,
            MatListModule,
            MatMenuModule,
            MatPaginatorModule,
            MatProgressBarModule,
            MatProgressSpinnerModule,
            MatRippleModule,
            MatSelectModule,
            MatSidenavModule,
            MatSliderModule,
            MatSlideToggleModule,
            MatSnackBarModule,
            MatSortModule,
            MatStepperModule,
            MatTabsModule,
            MatToolbarModule,
            MatTooltipModule,
            MatTreeModule,
            OverlayModule,
            PortalModule,
            BidiModule,
            A11yModule,
            MatCommonModule,
            ObserversModule,
            MatRadioModule,
            ScrollingModule,
            ScrollingModule$1,
            CdkTreeModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AngularMaterialModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: MATERIAL_MODULES,
                    exports: MATERIAL_MODULES,
                    providers: [
                        CdkTree,
                        CdkTreeNode,
                    ],
                }]
        }] });

// @dynamic
class NiceComponentLibraryModule {
    static forRoot(config) {
        return {
            ngModule: NiceComponentLibraryModule,
            providers: [
                ApiService, DateUtilService, FormStateService, UtilsService, LoaderService, ValidatorService,
                AuthoritiesService, AuthoritiesResolverService, SingletonTranslateService,
                { provide: InjectTokenNextSolutionsConfig, useValue: config ? config.data : {} }
            ],
        };
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NiceComponentLibraryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.5", ngImport: i0, type: NiceComponentLibraryModule, declarations: [CvaTableComponent,
            CvaSmartTableComponent,
            CvaInputComponent,
            CvaCounterInputComponent,
            CvaDatePickerComponent,
            CvaRangeDatePickerComponent,
            CvaMultiSelectAutocomplete,
            DragDropDirective,
            CvaMultiUploadComponent,
            CvaUploadFileComponent,
            CvaMultiUploadImgComponent,
            CvaBreadcrumbComponent,
            CvaLoaderComponent,
            CvaTreeComponent,
            CvaCustomDialogComponent,
            CvaRadiobuttonComponent,
            StylePaginatorDirective,
            SecureImgPipe,
            CvaFlatTreeComponent,
            CvaFlatTreeNodeLeftComponent,
            CvaFlatTreeNodeRightComponent,
            CvaHeaderExpandButtonComponent,
            PatternDirective,
            FormatInputDirective,
            CvaDialogImportFileComponent,
            BaseSearchComponent,
            BaseAddEditComponent,
            CvaQuillEditorComponent,
            CvaLiveSearchingComponent], imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            AngularMaterialModule, i1$4.RouterModule, i1.TranslateModule, i4$4.QuillModule, FlexLayoutModule], exports: [CvaTableComponent,
            CvaSmartTableComponent,
            CvaInputComponent,
            CvaCounterInputComponent,
            CvaDatePickerComponent,
            CvaRangeDatePickerComponent,
            CvaMultiSelectAutocomplete,
            DragDropDirective,
            CvaMultiUploadComponent,
            CvaUploadFileComponent,
            CvaMultiUploadImgComponent,
            CvaBreadcrumbComponent,
            CvaLoaderComponent,
            CvaTreeComponent,
            CvaCustomDialogComponent,
            CvaRadiobuttonComponent,
            StylePaginatorDirective,
            CvaFlatTreeComponent,
            SecureImgPipe,
            PatternDirective,
            FormatInputDirective,
            CvaFlatTreeNodeLeftComponent,
            CvaFlatTreeNodeRightComponent,
            CvaDialogImportFileComponent,
            BaseSearchComponent,
            BaseAddEditComponent,
            CvaQuillEditorComponent,
            CvaLiveSearchingComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NiceComponentLibraryModule, imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            AngularMaterialModule,
            RouterModule.forChild([]),
            TranslateModule.forChild(),
            QuillModule.forRoot(),
            FlexLayoutModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NiceComponentLibraryModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        FormsModule,
                        ReactiveFormsModule,
                        AngularMaterialModule,
                        RouterModule.forChild([]),
                        TranslateModule.forChild(),
                        QuillModule.forRoot(),
                        FlexLayoutModule,
                    ],
                    declarations: [
                        CvaTableComponent,
                        CvaSmartTableComponent,
                        CvaInputComponent,
                        CvaCounterInputComponent,
                        CvaDatePickerComponent,
                        CvaRangeDatePickerComponent,
                        CvaMultiSelectAutocomplete,
                        DragDropDirective,
                        CvaMultiUploadComponent,
                        CvaUploadFileComponent,
                        CvaMultiUploadImgComponent,
                        CvaBreadcrumbComponent,
                        CvaLoaderComponent,
                        CvaTreeComponent,
                        CvaCustomDialogComponent,
                        CvaRadiobuttonComponent,
                        StylePaginatorDirective,
                        SecureImgPipe,
                        CvaFlatTreeComponent,
                        CvaFlatTreeNodeLeftComponent,
                        CvaFlatTreeNodeRightComponent,
                        CvaHeaderExpandButtonComponent,
                        PatternDirective,
                        FormatInputDirective,
                        CvaDialogImportFileComponent,
                        BaseSearchComponent,
                        BaseAddEditComponent,
                        CvaQuillEditorComponent,
                        CvaLiveSearchingComponent,
                    ],
                    exports: [
                        CvaTableComponent,
                        CvaSmartTableComponent,
                        CvaInputComponent,
                        CvaCounterInputComponent,
                        CvaDatePickerComponent,
                        CvaRangeDatePickerComponent,
                        CvaMultiSelectAutocomplete,
                        DragDropDirective,
                        CvaMultiUploadComponent,
                        CvaUploadFileComponent,
                        CvaMultiUploadImgComponent,
                        CvaBreadcrumbComponent,
                        CvaLoaderComponent,
                        CvaTreeComponent,
                        CvaCustomDialogComponent,
                        CvaRadiobuttonComponent,
                        StylePaginatorDirective,
                        CvaFlatTreeComponent,
                        SecureImgPipe,
                        PatternDirective,
                        FormatInputDirective,
                        CvaFlatTreeNodeLeftComponent,
                        CvaFlatTreeNodeRightComponent,
                        CvaDialogImportFileComponent,
                        BaseSearchComponent,
                        BaseAddEditComponent,
                        CvaQuillEditorComponent,
                        CvaLiveSearchingComponent,
                    ],
                    schemas: [
                        NO_ERRORS_SCHEMA,
                        CUSTOM_ELEMENTS_SCHEMA,
                    ],
                }]
        }] });

/*
* Các cháu này là base class
* */

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

export { ActionTypeEnum, AlignEnum, ApiService, AuthoritiesResolverService, AuthoritiesService, Authority, BaseAddEditComponent, BaseModel, BaseSearchComponent, BaseStatusEnum, BaseTableComponent, BreadCrumbModel, ButtonClickEvent, ButtonModel, CheckboxModel, ColumnModel, ColumnTypeEnum, CustomDialogDataConfigModel, CvaBreadcrumbComponent, CvaCounterInputComponent, CvaCustomDialogComponent, CvaDatePickerComponent, CvaDialogImportFileComponent, CvaFlatTreeComponent, CvaFlatTreeNodeLeftComponent, CvaFlatTreeNodeRightComponent, CvaInputComponent, CvaLiveSearchingComponent, CvaLoaderComponent, CvaMultiSelectAutocomplete, CvaMultiUploadComponent, CvaMultiUploadImgComponent, CvaQuillEditorComponent, CvaRadiobuttonComponent, CvaRangeDatePickerComponent, CvaSmartTableComponent, CvaTableComponent, CvaTreeComponent, CvaUploadFileComponent, DateUtilService, DialogImportFileConfigModel, DialogTypeEnum, DragDropDirective, FileTypeEnum, FlatTreeConfigModel, FlatTreeModel, FlatTreeNodeModel, FormStateService, FormatInputDirective, IconTypeEnum, InjectTokenNextSolutionsConfig, JsogHttpInterceptor, LoaderInterceptor, LoaderService, MenuModel, MultiTranslateHttpLoader, NavigatorModel, NiceComponentLibraryModule, OAuth2AuthenticationDto, PatternDirective, PermissionModel, Principal, RangeDatePickerModel, RoleModel, SecureImgPipe, SelectModel, SingletonTranslateService, StylePaginatorDirective, TableFooterModel, TablePagingRequestModel, TablePagingResponseModel, TableService, UIState, UploadModel, UtilsService, ValidatorService };
//# sourceMappingURL=c10t-nice-component-library.mjs.map