import { of, Subject } from 'rxjs';
import { __awaiter, __classPrivateFieldGet, __classPrivateFieldSet } from 'tslib';
import { InjectionToken, ɵɵdefineInjectable, Injectable, Directive, TemplateRef, ViewContainerRef, Input, ElementRef, Renderer2, HostListener, IterableDiffers, NgModule } from '@angular/core';
import { FormControl } from '@angular/forms';
import { CommonModule } from '@angular/common';

Array.prototype.search = function (searchText, fields) {
    const items = this;
    if (!(searchText === null || searchText === void 0 ? void 0 : searchText.toString())) {
        return items;
    }
    if (Array.isArray(fields)) {
        const fs = fields.filter(e => e !== undefined && e !== null && e !== '');
        if (!fs.length) {
            return items.filter(item => item !== undefined && item !== null && String.aliasIncludes(item, searchText));
        }
        return items.filter(item => item !== undefined && item !== null && fs.some(field => String.aliasIncludes(item[field], searchText)));
    }
    if (!fields) {
        return items.filter(item => item !== undefined && item !== null && String.aliasIncludes(item, searchText));
    }
    return items.filter(item => item !== undefined && item !== null && String.aliasIncludes(item[fields], searchText));
};
Array.prototype.paging = function (pageSize, page = 0) {
    const items = this;
    return items.filter((item, index) => {
        return index >= page * pageSize && index < (page + 1) * pageSize;
    });
};
Array.prototype.toObject = function (key) {
    const items = this;
    if (!key) {
        return items
            .filter(item => item !== undefined && item !== null)
            .reduce((obj, item) => {
            obj[item === null || item === void 0 ? void 0 : item.toString()] = item;
            return obj;
        }, {});
    }
    return items
        .filter(item => item !== undefined && item !== null)
        .reduce((obj, item) => {
        var _a;
        obj[(_a = item[key]) === null || _a === void 0 ? void 0 : _a.toString()] = item;
        return obj;
    }, {});
};
Array.prototype.union = function (key, ...args) {
    let results = this;
    const filterUnion = (val, index, self) => val !== undefined && val !== null && self.findIndex((e) => (!!key ? e[key] === val[key] : e === val)) === index;
    if (!(args === null || args === void 0 ? void 0 : args.length)) {
        return results.filter(filterUnion);
    }
    for (const arg of args) {
        if (Array.isArray(arg)) {
            results = [...results, ...arg].filter(filterUnion);
        }
    }
    return results;
};
Array.prototype.asObservable = function () {
    const items = this;
    return of(items);
};
Array.search = (items, searchText, fields) => {
    if (!Array.isArray(items)) {
        return [];
    }
    return items.search(searchText, fields);
};
Array.union = (key, ...args) => {
    return [].union(key, ...args);
};
Array.toObject = (items, key) => {
    if (!Array.isArray(items)) {
        return {};
    }
    return items.toObject(key);
};
Array.sum = (items, key) => {
    return items === null || items === void 0 ? void 0 : items.map(e => +e[key] || 0).reduce((current, next) => current + next, 0);
};

Date.equal = (date1, date2) => {
    if (!Date.isDate(date1) && !Date.isDate(date2)) {
        return true;
    }
    if (!Date.isDate(date1) || !Date.isDate(date2)) {
        return false;
    }
    return new Date(date1).getTime() === new Date(date2).getTime();
};
Date.parseFrom = (value, format) => {
    if (!value) {
        return null;
    }
    if (!format) {
        return null;
    }
    value = value.toString();
    const dmy = format.indexOf('dd') > -1 && format.indexOf('MM') > -1 && format.indexOf('yyyy') > -1;
    const hms = format.indexOf('HH') > -1 || format.indexOf('mm') > -1 || format.indexOf('ss') > -1;
    let strDate = '';
    if (dmy) {
        const dd = value.substr(format.indexOf('dd'), 'dd'.length);
        const MM = value.substr(format.indexOf('MM'), 'MM'.length);
        const yyyy = value.substr(format.indexOf('yyyy'), 'yyyy'.length);
        if (+yyyy > 0 && +MM > 0 && +dd > 0) {
            strDate += `${MM}/${dd}/${yyyy}`;
        }
        else {
            return null;
        }
    }
    else {
        const today = new Date();
        const yyyy = today.getFullYear().toString();
        const MM = (today.getMonth() + 1).toString().padStart(2, '0');
        const dd = today.getDate().toString().padStart(2, '0');
        strDate += `${MM}/${dd}/${yyyy}`;
    }
    if (hms) {
        const HH = format.indexOf('HH') > -1 ? value.substr(format.indexOf('HH'), 'HH'.length) : '00';
        const mm = format.indexOf('mm') > -1 ? value.substr(format.indexOf('mm'), 'mm'.length) : '00';
        const ss = format.indexOf('ss') > -1 ? value.substr(format.indexOf('ss'), 'ss'.length) : '00';
        strDate += ` ${HH || '00'}:${mm || '00'}:${ss || '00'}`;
    }
    if (!Date.isDate(strDate)) {
        return null;
    }
    return new Date(strDate);
};
Date.isDate = (value) => {
    if (!value) {
        return false;
    }
    const date = new Date(value);
    return !isNaN(date.getTime());
};
Date.toFormat = (value, format) => {
    if (!Date.isDate(value)) {
        return '';
    }
    const date = new Date(value);
    return date.toFormat(format);
};
Date.addMiliseconds = (value, miliseconds) => {
    if (!Date.isDate(value)) {
        return null;
    }
    const date = new Date(value);
    return date.addMiliseconds(miliseconds);
};
Date.addHours = (value, hours) => {
    if (!Date.isDate(value)) {
        return null;
    }
    const date = new Date(value);
    return date.addHours(hours);
};
Date.addDays = (value, days) => {
    if (!Date.isDate(value)) {
        return null;
    }
    const date = new Date(value);
    return date.addDays(days);
};
Date.addMonths = (value, months) => {
    if (!Date.isDate(value)) {
        return null;
    }
    const date = new Date(value);
    return date.addMonths(months);
};
Date.begin = (value) => {
    if (!Date.isDate(value)) {
        return null;
    }
    return new Date(Date.toFormat(value, 'MM/dd/yyyy'));
};
Date.end = (value) => {
    if (!Date.isDate(value)) {
        return null;
    }
    return new Date(value).addDays(1).begin().addMiliseconds(-1);
};
Date.diffDays = (from, to) => {
    if (!Date.isDate(from) || !Date.isDate(to)) {
        return undefined;
    }
    const diffTime = new Date(to).getTime() - new Date(from).getTime();
    const diffDays = Math.round((diffTime / (1000 * 60 * 60 * 24)) * 100) / 100;
    return diffDays;
};
Date.prototype.begin = function () {
    return new Date(this.toFormat('MM/dd/yyyy'));
};
Date.prototype.end = function () {
    const date = this;
    return date.addDays(1).begin().addMiliseconds(-1);
};
Date.prototype.addMiliseconds = function (miliseconds) {
    const date = this;
    date.setMilliseconds(date.getMilliseconds() + miliseconds);
    return date;
};
Date.prototype.addHours = function (hours) {
    const date = this;
    date.setHours(date.getHours() + hours);
    return date;
};
Date.prototype.addDays = function (days) {
    const date = this;
    date.setDate(date.getDate() + days);
    return date;
};
Date.prototype.addMonths = function (months) {
    const date = this;
    date.setMonth(date.getMonth() + months);
    return date;
};
Date.prototype.toFormat = function (format) {
    const date = this;
    let result = format;
    result = result.replace('yyyy', date.getFullYear().toString());
    result = result.replace('MM', (date.getMonth() + 1).toString().padStart(2, '0'));
    result = result.replace('dd', date.getDate().toString().padStart(2, '0'));
    result = result.replace('HH', date.getHours().toString().padStart(2, '0'));
    result = result.replace('mm', date.getMinutes().toString().padStart(2, '0'));
    result = result.replace('ss', date.getSeconds().toString().padStart(2, '0'));
    return result;
};

Number.toVNCurrency = (value, digits) => {
    value = (value !== null && value !== void 0 ? value : '').toString().replace(/,/g, '');
    if (!value) {
        return null;
    }
    const val = +value;
    if (!Number.isNaN(val)) {
        if (!digits && digits !== 0) {
            return val.toLocaleString('vi-VN', { maximumFractionDigits: 10 });
        }
        return val.toLocaleString('vi-VN', { maximumFractionDigits: digits });
    }
    return null;
};
Number.isPositiveInteger = (value) => {
    if (!value) {
        return false;
    }
    const regex = /^([0-9]*)$/;
    return regex.test(value) && +value > 0;
};
Number.isPositiveNumber = (value) => {
    if (!value) {
        return false;
    }
    const regex = /^([0-9]*)(\.[0-9]+$){0,1}$/;
    return regex.test(value) && +value > 0;
};
Number.isNumber = (value) => {
    if (value === undefined || value === null || value === '') {
        return false;
    }
    return !Number.isNaN(+value);
};
Number.round = (value, digits) => {
    digits = digits !== null && digits !== void 0 ? digits : 2;
    if (!Number.isNumber(value)) {
        return null;
    }
    const val = Math.pow(10, digits);
    return Math.round(value * val) / val;
};

String.isValidEmail = (value) => {
    if (!value) {
        return false;
    }
    const re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
    return re.test(value);
};
String.isValidPhone = (value) => {
    if (!value) {
        return false;
    }
    const re = /^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$/;
    return re.test(value);
};
String.isValidCode = (value) => {
    if (!value) {
        return false;
    }
    const re = /^[a-zA-Z0-9\@\_\-]{2,20}$/;
    return re.test(value);
};
String.isNullOrEmpty = (value) => {
    return value === undefined || value === null || value === '';
};
String.isNullOrWhiteSpace = (value) => {
    return value === undefined || value === null || typeof value !== 'string' || value.match(/^ *$/) !== null;
};
String.changeAliasLowerCase = (alias) => {
    var _a;
    let str = (_a = alias === null || alias === void 0 ? void 0 : alias.toString()) !== null && _a !== void 0 ? _a : '';
    str = str.toString().toLowerCase();
    str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a');
    str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e');
    str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i');
    str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o');
    str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u');
    str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y');
    str = str.replace(/đ/g, 'd');
    str = str.replace(/!|@|%|\^|\*|\(|\)|\+|\=|\<|\>|\?|\/|,|\.|\:|\;|\'|\"|\&|\#|\[|\]|~|\$|_|`|-|{|}|\||\\/g, ' ');
    str = str.replace(/ + /g, ' ');
    str = str.trim();
    return str;
};
String.aliasIncludes = (alias, searchText) => {
    return String.changeAliasLowerCase(alias).includes(String.changeAliasLowerCase(searchText));
};
String.format = (template, ...arr) => {
    for (let i = 0; i < arr.length; i++) {
        const regexp = new RegExp(`\\{${i}\\}`, 'gi');
        template = template.replace(regexp, arr[i]);
    }
    return template;
};
String.templateToDisplay = (template, entity) => {
    if (!template) {
        return template;
    }
    const regex = /\$\{([A-Za-z._\-]*)\}/g;
    const matches = template.match(regex) || [];
    for (const match of matches) {
        const key = match.slice(2, match.length - 1);
        if (key) {
            template = template.replace(match, (entity === null || entity === void 0 ? void 0 : entity[key]) || '');
        }
    }
    return template;
};
const SALT = 'cb9f4b2a-d26c-4787-a66e-e7130ee00f95';
String.encrypt = (obj) => {
    obj = JSON.stringify(obj).split('');
    for (var i = 0, l = obj.length; i < l; i++)
        if (obj[i] == '{')
            obj[i] = '}';
        else if (obj[i] == '}')
            obj[i] = '{';
    return encodeURI(SALT + obj.join(''));
};
String.decrypt = (encripted) => {
    encripted = decodeURI(encripted);
    if (SALT && encripted.indexOf(SALT) != 0)
        throw new Error('object cannot be decrypted');
    const strs = encripted.substring(SALT.length).split('');
    for (let i = 0, l = strs.length; i < l; i++)
        if (strs[i] == '{')
            strs[i] = '}';
        else if (encripted[i] == '}')
            strs[i] = '{';
    return JSON.parse(strs.join(''));
};

/**
 *
 * detectIncognito v1.3.0 - (c) 2022 Joe Rutkowski <Joe@dreggle.com> (https://github.com/Joe12387/detectIncognito)
 *
 **/
const detectIncognito = () => {
    return new Promise((resolve, reject) => {
        let browserName = 'Unknown';
        function __callback(isPrivate) {
            resolve({
                isPrivate,
                browserName,
            });
        }
        function identifyChromium() {
            const ua = navigator.userAgent;
            if (ua.match(/Chrome/)) {
                if (navigator.brave !== undefined) {
                    return 'Brave';
                }
                else if (ua.match(/Edg/)) {
                    return 'Edge';
                }
                else if (ua.match(/OPR/)) {
                    return 'Opera';
                }
                return 'Chrome';
            }
            else {
                return 'Chromium';
            }
        }
        function assertEvalToString(value) {
            return value === eval.toString().length;
        }
        function isSafari() {
            const v = navigator.vendor;
            return (v !== undefined && v.indexOf('Apple') === 0 && assertEvalToString(37));
        }
        function isChrome() {
            const v = navigator.vendor;
            return (v !== undefined && v.indexOf('Google') === 0 && assertEvalToString(33));
        }
        function isFirefox() {
            return (document.documentElement !== undefined &&
                document.documentElement.style.MozAppearance !== undefined &&
                assertEvalToString(37));
        }
        function isMSIE() {
            return (navigator.msSaveBlob !== undefined && assertEvalToString(39));
        }
        /**
         * Safari (Safari for iOS & macOS)
         **/
        function newSafariTest() {
            // tslint:disable-next-line:variable-name
            const tmp_name = String(Math.random());
            try {
                const db = window.indexedDB.open(tmp_name, 1);
                db.onupgradeneeded = (i) => {
                    var _a, _b;
                    // @ts-ignore
                    const res = (_a = i.target) === null || _a === void 0 ? void 0 : _a.result;
                    try {
                        res.createObjectStore('test', {
                            autoIncrement: true,
                        }).put(new Blob);
                        __callback(false);
                    }
                    catch (e) {
                        let message = e;
                        if (e instanceof Error) {
                            message = (_b = e.message) !== null && _b !== void 0 ? _b : e;
                        }
                        if (typeof message !== 'string') {
                            return __callback(false);
                        }
                        const matchesExpectedError = /BlobURLs are not yet supported/.test(message);
                        return __callback(matchesExpectedError);
                    }
                    finally {
                        res.close();
                        window.indexedDB.deleteDatabase(tmp_name);
                    }
                };
            }
            catch (e) {
                return __callback(false);
            }
        }
        function oldSafariTest() {
            const openDB = window.openDatabase;
            const storage = window.localStorage;
            try {
                openDB(null, null, null, null);
            }
            catch (e) {
                return __callback(true);
            }
            try {
                storage.setItem('test', '1');
                storage.removeItem('test');
            }
            catch (e) {
                return __callback(true);
            }
            return __callback(false);
        }
        function safariPrivateTest() {
            if (navigator.maxTouchPoints !== undefined) {
                newSafariTest();
            }
            else {
                oldSafariTest();
            }
        }
        /**
         * Chrome
         **/
        function getQuotaLimit() {
            const w = window;
            if (w.performance !== undefined &&
                w.performance.memory !== undefined &&
                w.performance.memory.jsHeapSizeLimit !== undefined) {
                return performance.memory.jsHeapSizeLimit;
            }
            return 1073741824;
        }
        // >= 76
        function storageQuotaChromePrivateTest() {
            navigator.webkitTemporaryStorage.queryUsageAndQuota((_, quota) => {
                const quotaInMib = Math.round(quota / (1024 * 1024));
                const quotaLimitInMib = Math.round(getQuotaLimit() / (1024 * 1024)) * 2;
                __callback(quotaInMib < quotaLimitInMib);
            }, (e) => {
                reject(new Error('detectIncognito somehow failed to query storage quota: ' +
                    e.message));
            });
        }
        // 50 to 75
        function oldChromePrivateTest() {
            const fs = window.webkitRequestFileSystem;
            const success = () => {
                __callback(false);
            };
            const error = () => {
                __callback(true);
            };
            fs(0, 1, success, error);
        }
        function chromePrivateTest() {
            if (self.Promise !== undefined && self.Promise.allSettled !== undefined) {
                storageQuotaChromePrivateTest();
            }
            else {
                oldChromePrivateTest();
            }
        }
        /**
         * Firefox
         **/
        function firefoxPrivateTest() {
            __callback(navigator.serviceWorker === undefined);
        }
        /**
         * MSIE
         **/
        function msiePrivateTest() {
            __callback(window.indexedDB === undefined);
        }
        function main() {
            if (isSafari()) {
                browserName = 'Safari';
                safariPrivateTest();
            }
            else if (isChrome()) {
                browserName = identifyChromium();
                chromePrivateTest();
            }
            else if (isFirefox()) {
                browserName = 'Firefox';
                firefoxPrivateTest();
            }
            else if (isMSIE()) {
                browserName = 'Internet Explorer';
                msiePrivateTest();
            }
            else {
                reject(new Error('detectIncognito cannot determine the browser'));
            }
        }
        main();
    });
};

const upload = (option) => {
    const uploadId = 'U1e09c1c0-b647-437e-995e-d7a1a1b60550';
    const promise = new Promise((resolve, reject) => {
        var _a;
        const body = (_a = document.getElementsByTagName('body')) === null || _a === void 0 ? void 0 : _a[0];
        if (!body) {
            resolve(null);
            return;
        }
        const existedElement = document.getElementById(uploadId);
        if (existedElement) {
            existedElement.remove();
        }
        const element = document.createElement('input');
        element.setAttribute('id', uploadId);
        element.setAttribute('type', 'file');
        element.style.display = 'none';
        body.appendChild(element);
        element.addEventListener('change', (evt) => {
            var _a;
            try {
                const target = evt.target;
                const file = target.files.item(0);
                if (file) {
                    const lastDot = file.name.lastIndexOf('.');
                    if (lastDot === -1) {
                        throw new Error(`File không đúng định dạng`);
                    }
                    const extension = file.name.substring(lastDot + 1);
                    if (option) {
                        if (((_a = option.extensions) === null || _a === void 0 ? void 0 : _a.length) && !option.extensions.some(e => e.toUpperCase() === extension.toUpperCase())) {
                            throw new Error(`File không đúng định dạng`);
                        }
                        if (option.maxSizeInMb && option.maxSizeInMb > 0 && option.maxSizeInMb * 1024 * 1024 < file.size) {
                            const message = `[${file.name}] Dung lượng tối đa ${option.maxSizeInMb} Mbs`;
                            throw new Error(message);
                        }
                        if (option.validator && option.validator(file.name)) {
                            const message = option.validator(file.name);
                            throw new Error(message);
                        }
                    }
                    resolve(file);
                }
            }
            catch (error) {
                reject(error);
            }
        });
        element.click();
    });
    return promise;
};
const ɵ0 = upload;
const generateFileName = (fileName) => {
    if (!fileName) {
        return `File_${new Date().toFormat('yyyy_MM_dd_HH_mm')}`;
    }
    const strs = fileName.split('.');
    if (strs.length > 1) {
        const ext = strs.splice(strs.length - 1, 1)[0];
        return `${strs.join('.')}_${new Date().toFormat('yyyy_MM_dd_HH_mm')}.${ext}`;
    }
    return `${fileName}_${new Date().toFormat('yyyy_MM_dd_HH_mm')}`;
};
const ɵ1 = generateFileName;
const download = (filePath, fileName) => {
    const link = document.createElement('a');
    link.download = generateFileName(fileName);
    link.href = filePath;
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    link.remove();
};
const ɵ2 = download;
const downloadBlob = (blob, fileName) => {
    try {
        const url = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        if (link.download !== undefined) { // feature detection
            link.download = generateFileName(fileName);
            link.href = url;
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            window.URL.revokeObjectURL(url);
            link.remove();
        }
    }
    catch (e) {
        console.error('BlobToSaveAs error', e);
    }
};
const ɵ3 = downloadBlob;
const changeAliasLowerCase = (alias) => {
    var _a;
    let str = (_a = alias === null || alias === void 0 ? void 0 : alias.toString()) !== null && _a !== void 0 ? _a : '';
    str = str.toString().toLowerCase();
    str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a');
    str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e');
    str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i');
    str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o');
    str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u');
    str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y');
    str = str.replace(/đ/g, 'd');
    str = str.replace(/!|@|%|\^|\*|\(|\)|\+|\=|\<|\>|\?|\/|,|\.|\:|\;|\'|\"|\&|\#|\[|\]|~|\$|_|`|-|{|}|\||\\/g, ' ');
    str = str.replace(/ + /g, ' ');
    str = str.trim();
    return str;
};
const ɵ4 = changeAliasLowerCase;
const copyToClipboard = (text) => {
    navigator.clipboard.writeText(text);
};
const ɵ5 = copyToClipboard;
const allWithPaging = (func, defaultPageSize) => __awaiter(void 0, void 0, void 0, function* () {
    var _a;
    let pageSize = defaultPageSize || 1000;
    let pageNumber = 0;
    let count = 0;
    let items = [];
    while (true) {
        const res = yield func(pageSize, pageNumber);
        if (Array(res === null || res === void 0 ? void 0 : res.items) && (res === null || res === void 0 ? void 0 : res.total) > 0) {
            items = [...items, ...res.items];
            count += res.items.length;
            pageNumber++;
            if (count >= res.total || !((_a = res.items) === null || _a === void 0 ? void 0 : _a.length)) {
                return items;
            }
        }
        else {
            return [];
        }
    }
});
const ɵ6 = allWithPaging;
const isPrivateMode = () => __awaiter(void 0, void 0, void 0, function* () {
    const check = yield detectIncognito();
    return check.isPrivate;
});
const ɵ7 = isPrivateMode;
var SdUtility = {
    upload,
    download,
    downloadBlob,
    changeAliasLowerCase,
    copyToClipboard,
    allWithPaging,
    isPrivateMode,
};
globalThis.SdUtility = SdUtility;

const FIREBASE_CONFIG = new InjectionToken('sd.firebase.configuration');

const FORM_CONFIG = new InjectionToken('sd.form.configuration');

class SdFormControl extends FormControl {
    constructor(formState, validator = null, asyncValidator = null) {
        super(formState, validator, asyncValidator);
        this.sdChanges = new Subject();
        this.untouchChanges = new Subject();
        this.touchChanges = new Subject();
        this.pristineChanges = new Subject();
    }
    markAsUntouched({ onlySelf } = {}) {
        super.markAsUntouched({ onlySelf });
        this.untouchChanges.next(true);
        this.sdChanges.next(true);
    }
    markAsTouched({ onlySelf } = {}) {
        super.markAsTouched({ onlySelf });
        this.touchChanges.next(true);
        this.sdChanges.next(true);
    }
    markAsPristine(opts) {
        super.markAsPristine(opts);
        this.pristineChanges.next(true);
        this.sdChanges.next(true);
    }
}

var _getBrowserNameAndVersion;
class SdBrowserService {
    constructor() {
        _getBrowserNameAndVersion.set(this, () => {
            const ua = navigator.userAgent;
            let M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
            let tem;
            if (/trident/i.test(M[1])) {
                tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
                return { name: 'IE', version: (tem[1] || '') };
            }
            if (M[1] === 'Chrome') {
                tem = ua.match(/\bEdg\/(\d+)/);
                if (tem != null) {
                    return { name: 'Edge(Chromium)', version: tem[1] };
                }
                tem = ua.match(/\bOPR\/(\d+)/);
                if (tem != null) {
                    return { name: 'Opera', version: tem[1] };
                }
            }
            M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
            tem = ua.match(/version\/(\d+)/i);
            if (tem != null) {
                M.splice(1, 1, tem[1]);
            }
            return {
                name: M[0],
                version: M[1]
            };
        });
        const browserNameAndVersion = __classPrivateFieldGet(this, _getBrowserNameAndVersion).call(this);
        this.browerName = browserNameAndVersion.name;
        this.browserVersion = browserNameAndVersion.version;
    }
    get isChrome() { return this.browerName === 'Chrome'; }
    get isFirefox() { return this.browerName === 'Firefox'; }
    get isSafari() { return this.browerName === 'Safari'; }
}
_getBrowserNameAndVersion = new WeakMap();
SdBrowserService.ɵprov = ɵɵdefineInjectable({ factory: function SdBrowserService_Factory() { return new SdBrowserService(); }, token: SdBrowserService, providedIn: "root" });
SdBrowserService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root'
            },] }
];
SdBrowserService.ctorParameters = () => [];

class SdViewDefDirective {
    // @Input() sdViewDef: string;
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
}
SdViewDefDirective.decorators = [
    { type: Directive, args: [{
                selector: '[sdViewDef]'
            },] }
];
SdViewDefDirective.ctorParameters = () => [
    { type: TemplateRef }
];

var _updateView;
class SdLetDirective {
    constructor(vcRef, templateRef) {
        this.vcRef = vcRef;
        this.templateRef = templateRef;
        this.context = {};
        _updateView.set(this, () => {
            this.vcRef.clear();
            this.vcRef.createEmbeddedView(this.templateRef, this.context);
        });
    }
    set sdLet(context) {
        this.context.$implicit = this.context.sdLet = context;
        __classPrivateFieldGet(this, _updateView).call(this);
    }
}
_updateView = new WeakMap();
SdLetDirective.decorators = [
    { type: Directive, args: [{
                selector: '[sdLet]',
            },] }
];
SdLetDirective.ctorParameters = () => [
    { type: ViewContainerRef },
    { type: TemplateRef }
];
SdLetDirective.propDecorators = {
    sdLet: [{ type: Input }]
};

var _overflow;
class SdScrollDirective {
    constructor(elementRef, renderer, browserService) {
        this.elementRef = elementRef;
        this.renderer = renderer;
        this.browserService = browserService;
        _overflow.set(this, 'hidden');
        this.scrollTop = () => {
            setTimeout(() => {
                var _a;
                if ((_a = this.elementRef) === null || _a === void 0 ? void 0 : _a.nativeElement) {
                    this.elementRef.nativeElement.scrollTop = 0;
                }
            }, 1);
        };
    }
    onMouseOver() {
        __classPrivateFieldSet(this, _overflow, this.browserService.isFirefox ? 'auto' : 'overlay');
        this.renderer.setStyle(this.elementRef.nativeElement, 'overflow', __classPrivateFieldGet(this, _overflow));
    }
    onMouseOut() {
        __classPrivateFieldSet(this, _overflow, 'hidden');
        this.renderer.setStyle(this.elementRef.nativeElement, 'overflow', __classPrivateFieldGet(this, _overflow));
    }
    ngOnInit() {
        this.renderer.setStyle(this.elementRef.nativeElement, '-webkit-transform', 'translate3d(0, 0, 0)');
        this.renderer.setStyle(this.elementRef.nativeElement, 'overflow', __classPrivateFieldGet(this, _overflow));
    }
}
_overflow = new WeakMap();
SdScrollDirective.decorators = [
    { type: Directive, args: [{
                selector: "[sdScroll]",
            },] }
];
SdScrollDirective.ctorParameters = () => [
    { type: ElementRef },
    { type: Renderer2 },
    { type: SdBrowserService }
];
SdScrollDirective.propDecorators = {
    onMouseOver: [{ type: HostListener, args: ['mouseover',] }],
    onMouseOut: [{ type: HostListener, args: ['mouseout',] }]
};

class SdSuffixDirective {
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
}
SdSuffixDirective.decorators = [
    { type: Directive, args: [{
                selector: '[sdSuffix]'
            },] }
];
SdSuffixDirective.ctorParameters = () => [
    { type: TemplateRef }
];

class SdLabelDefDirective {
    // @Input() sdLableDef: string;
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
}
SdLabelDefDirective.decorators = [
    { type: Directive, args: [{
                selector: '[sdLabelDef]'
            },] }
];
SdLabelDefDirective.ctorParameters = () => [
    { type: TemplateRef }
];

class SdForDirective {
    constructor(templateRef, viewContainer, differs) {
        this.templateRef = templateRef;
        this.viewContainer = viewContainer;
        this.differs = differs;
        this.items = [];
        this.viewRefsMap = new Map();
        this.itemsAtOnce = 20;
        this.intervalLength = 50;
    }
    set sdForOf(items) {
        this.items = items;
        if (items) {
            this._diffrence = this.differs.find(items).create();
        }
        //Clear any existing items
        this.viewContainer.clear();
    }
    ngDoCheck() {
        if (this._diffrence) {
            const changes = this._diffrence.diff(this.items);
            if (changes) {
                const itemsAdded = [];
                changes.forEachAddedItem(item => {
                    itemsAdded.push(item);
                });
                this.progressiveRender(itemsAdded);
                changes.forEachRemovedItem(item => {
                    const mapView = this.viewRefsMap.get(item.item);
                    const viewIndex = this.viewContainer.indexOf(mapView);
                    this.viewContainer.remove(viewIndex);
                    this.viewRefsMap.delete(item.item);
                });
            }
        }
    }
    progressiveRender(items) {
        let interval;
        let start = 0;
        let end = start + this.itemsAtOnce;
        if (end > items.length) {
            end = items.length;
        }
        this.renderItems(items, start, end);
        interval = setInterval(() => {
            start = end;
            end = start + this.itemsAtOnce;
            if (end > items.length) {
                end = items.length;
            }
            this.renderItems(items, start, end);
            if (start >= items.length) {
                clearInterval(interval);
            }
        }, this.intervalLength);
    }
    renderItems(items, start, end) {
        items.slice(start, end).forEach(item => {
            const embeddedView = this.viewContainer.createEmbeddedView(this.templateRef, {
                $implicit: item.item
            }, item.currentIndex || 0);
            this.viewRefsMap.set(item.item, embeddedView);
        });
    }
}
SdForDirective.decorators = [
    { type: Directive, args: [{
                selector: '[sdFor]'
            },] }
];
SdForDirective.ctorParameters = () => [
    { type: TemplateRef },
    { type: ViewContainerRef },
    { type: IterableDiffers }
];
SdForDirective.propDecorators = {
    sdForOf: [{ type: Input, args: ['sdForOf',] }],
    itemsAtOnce: [{ type: Input, args: ['sdForItemsAtOnce',] }],
    intervalLength: [{ type: Input, args: ['sdForIntervalLength',] }]
};

// import './typings';
class SdCommonModule {
}
SdCommonModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule
                ],
                declarations: [
                    SdForDirective,
                    SdViewDefDirective,
                    SdLetDirective,
                    SdScrollDirective,
                    SdSuffixDirective,
                    SdLabelDefDirective
                ],
                exports: [
                    SdForDirective,
                    SdViewDefDirective,
                    SdLetDirective,
                    SdScrollDirective,
                    SdSuffixDirective,
                    SdLabelDefDirective
                ],
                providers: []
            },] }
];

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

export { FIREBASE_CONFIG, FORM_CONFIG, SdBrowserService, SdCommonModule, SdFormControl, SdLabelDefDirective, SdLetDirective, SdScrollDirective, SdSuffixDirective, SdViewDefDirective, SdForDirective as ɵa };
//# sourceMappingURL=sd-angular-core-common.js.map
