UNPKG

ngx-gem-spaas

Version:

This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.

2,239 lines 145 kB
import * as i0 from '@angular/core';
import { Component, Injectable, Optional, Inject, Input, EventEmitter, Output, NgModule, ViewChild, Directive, HostListener, APP_INITIALIZER } from '@angular/core';
import * as i6 from '@angular/common';
import { CommonModule } from '@angular/common';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Subject, ReplaySubject, BehaviorSubject, timer, filter, fromEvent } from 'rxjs';
import { takeUntil, take, map } from 'rxjs/operators';
import * as i3 from '@angular/router';
import { NavigationStart, RouterModule } from '@angular/router';
import { OktaAuth } from '@okta/okta-auth-js';
import * as i4 from '@angular/material/progress-bar';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import * as i4$1 from '@angular/forms';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i5 from '@angular/material/radio';
import { MatRadioModule, MAT_RADIO_DEFAULT_OPTIONS } from '@angular/material/radio';
import * as i2 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i1$1 from '@angular/material/snack-bar';
import { MatSnackBarModule, MatSnackBarConfig } from '@angular/material/snack-bar';
import * as i4$2 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import * as i1 from '@angular/material/bottom-sheet';
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
import * as i3$2 from '@angular/cdk/drag-drop';
import { DragDropModule } from '@angular/cdk/drag-drop';
import * as i2$1 from '@angular/service-worker';
import { ServiceWorkerModule } from '@angular/service-worker';
import * as i3$1 from '@angular/cdk/platform';
import * as i2$2 from '@angular/platform-browser';

class BaseComponent {
    constructor() {
        this.onDestroy$ = new Subject();
    }
    ngOnDestroy() {
        this.onDestroy$.next();
        this.onDestroy$.complete();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: BaseComponent, selector: "spaas-base", ngImport: i0, template: '', isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BaseComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'spaas-base',
                    template: '',
                }]
        }] });

/**
 * Okta configuration object to be provided via "forRoot" method of the SpaasModule.
 *
 * @property {string[]} additionalScopes the scopes needed for your particular back-end
 * @property {string} clientId the client id of your SPA
 * @property {string[]} interceptUrls the urls to intercept and add an Authorization - Bearer header to
 * @property {string} tenantId the tenant id of your Okta issuer
 * @property {string} url the url of your Okta issuer
 * @property {boolean} withPath false for subdomains, true for context (optional, default is true)
 */
class OktaConfigModel {
    constructor(objIn) {
        this.additionalScopes = [];
        this.clientId = '';
        this.interceptUrls = [];
        this.tenantId = '';
        this.url = '';
        this.withPath = true;
        this.additionalScopes = objIn.additionalScopes || [];
        this.clientId = objIn.clientId || '';
        this.interceptUrls = objIn.interceptUrls || [];
        this.tenantId = objIn.tenantId || '';
        this.url = objIn.url || '';
        this.withPath = objIn.withPath || true;
    }
}
class OktaUserModel {
    constructor(props) {
        const nameArr = OktaUserModel.stripMail(props.email).split('.');
        this.email = props.email || '';
        this.firstName = nameArr.length ? nameArr[0] : '';
        this.groups = props.groups || [];
        this.lastName = nameArr.length ? nameArr[1] : '';
        this.userId = props.userid || props.userId || ''; // props.userId is for when OktaUserModel is extended and fed itself as props
    }
    static stripMail(strIn) {
        return strIn ? strIn.replace('@engie.com', '').replace('@external.engie.com', '') : '';
    }
    checkGroup(group) {
        return this.groups.some((g) => g.toLowerCase().startsWith((group || '').toLowerCase()));
    }
}

/**
 * New version configuration object to be provided via "forRoot" method of the SpaasModule.
 *
 * @property {number} reminder default is zero. If not zero and hasBackdrop === true, this sets the interval
 * (in minutes) at which to prompt the user to load the newly deployed version. Will be floored to a 5-minute minimum.
 * @property {boolean} hasBackdrop default is true. If false, no backdrop is shown for the bottom-sheet pop-up (and
 * so the pop-up can only be dismissed by accepting the new version).
 */
class NewVersionConfigModel {
    constructor(objIn) {
        this.reminder = 0;
        this.hasBackdrop = true;
        this.reminder = objIn.reminder ? Math.max(objIn.reminder, 5) : 0;
        this.hasBackdrop = objIn.hasOwnProperty('hasBackdrop') ? objIn.hasBackdrop : true;
    }
}

/**
 * Library configuration object to be provided via "forRoot" method of the SpaasModule.
 *
 * @property {string} appName the application name. Will be shown in browser tab and will be used as storage prefix
 * @property {string} environment will be used as storage prefix, in combination with appName
 * @property {OktaConfigModel} oktaConfig the Okta configuration for this project
 * @property {NewVersionConfigModel} newVersionConfig the configuration for the new version handling
 */
class SpaasConfigModel {
    constructor(objIn) {
        this.appName = '';
        this.environment = '';
        this.oktaConfig = new OktaConfigModel({});
        this.newVersionConfig = new NewVersionConfigModel({});
        this.appName = objIn.appName || '';
        this.environment = objIn.environment || '';
        this.oktaConfig = new OktaConfigModel(objIn.oktaConfig || {});
        this.newVersionConfig = new NewVersionConfigModel(objIn.newVersionConfig || {});
    }
}
class SpaasExtConfigModel extends SpaasConfigModel {
    constructor(conf) {
        super(conf);
        this.cleanAppName = this.appName.charAt(0).toUpperCase() + this.appName.substring(1, this.appName.length).toLowerCase();
        this.storagePrefix = (this.appName || this.oktaConfig?.clientId) + '-' + this.environment + '-';
    }
}

class ConfigService {
    constructor(spaasConfig) {
        this.spaasConfig = spaasConfig;
        if (!spaasConfig) {
            throw new Error('please provide a SpaasConfigModel using the forRoot method of the SpaasModule');
        }
        this.config = new SpaasExtConfigModel(this.spaasConfig);
    }
    getConfig() {
        return this.config;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConfigService, deps: [{ token: SpaasConfigModel, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConfigService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConfigService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: SpaasConfigModel, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [SpaasConfigModel]
                }] }] });

var EmbedModeEnum;
(function (EmbedModeEnum) {
    EmbedModeEnum["none"] = "";
    EmbedModeEnum["iframe"] = "iframe";
})(EmbedModeEnum || (EmbedModeEnum = {}));
class EmbedModeModel {
    constructor() {
        this.parent = '';
        this.pwd = '';
        this.type = EmbedModeEnum.none;
        this.usr = '';
    }
    isIframe() {
        return this.type === EmbedModeEnum.iframe;
    }
}

class EmbedModeService {
    constructor() {
        this.POST_MESSAGE_GETTHEME = 'getTheme';
        this.embedMode = new EmbedModeModel();
        this.embedMode$ = new ReplaySubject(1);
        this.embeddedWindow = null;
    }
    static getIframeParent() {
        const ref = document.referrer || '';
        if (ref) {
            const url = new URL(ref);
            if (url.pathname !== '/') {
                return url.pathname.replace(/\//g, '');
            }
            else {
                const subdomain = url.hostname.split('.')[0] || '';
                if (!subdomain.includes('cylon')) {
                    return subdomain;
                }
            }
        }
        return '';
    }
    // setEmbedMode is called from the app-init.service
    setEmbedMode() {
        if (window.location !== window.parent.location) {
            // iframe mode
            this.embedMode.type = EmbedModeEnum.iframe;
            this.embedMode.parent = EmbedModeService.getIframeParent();
        }
        this.newEmbedMode();
    }
    // ********************************************************************************************************
    // LOAD DATA
    // ********************************************************************************************************
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newEmbedMode() {
        // console.log('embed mode set: ' + (this.embedMode.type || 'none'));
        this.embedMode$.next(this.embedMode);
    }
    onNewEmbedMode() {
        return this.embedMode$.asObservable();
    }
    getEmbedMode() {
        return this.embedMode;
    }
    getEmbeddedWindow() {
        return this.embeddedWindow;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbedModeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbedModeService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbedModeService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }] });

class UtilsService {
    static copy(objIn) {
        return JSON.parse(JSON.stringify(objIn));
    }
    // DISTINCT SORTED LIST WITHOUT NULL/UNDEFINED VALUES
    static distinct(listIn, prefix = '', sortAsc = true) {
        const sortCorr = sortAsc ? 1 : -1;
        let listOut = listIn
            .filter((value, index, self) => value && self.indexOf(value) === index)
            .sort((a, b) => a < b ? -1 * sortCorr : 1 * sortCorr);
        if (prefix) {
            listOut = listOut.map((c) => prefix + c);
        }
        return listOut;
    }
    static round(num, dec) {
        if (num === null || num === undefined) {
            return null;
        }
        return Number((num).toFixed(dec));
    }
    static checkJSON(itemToCheck) {
        let item = {};
        try {
            item = JSON.parse(itemToCheck);
        }
        catch (e) {
            return false;
        }
        return typeof item === 'object' && item !== null;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilsService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }] });

class LocalStorageService {
    constructor(configService) {
        this.configService = configService;
        this.storagePrefix = this.configService.getConfig().storagePrefix;
    }
    getItem(lsKey) {
        const lsVal = localStorage.getItem(this.storagePrefix + lsKey) || '';
        return UtilsService.checkJSON(lsVal) ? JSON.parse(lsVal) : Number.isNaN(Number(lsVal)) ? lsVal : Number(lsVal);
    }
    getItems(searchString) {
        const tempResults = [];
        for (const key in localStorage) {
            if (localStorage.hasOwnProperty(key)) {
                if (key.indexOf(searchString) > -1) {
                    if (UtilsService.checkJSON(localStorage[key])) {
                        tempResults.push(JSON.parse(localStorage[key]));
                    }
                    else {
                        tempResults.push(localStorage[key]);
                    }
                }
            }
        }
        return tempResults;
    }
    setItem(lsKey, lsValue) {
        if (typeof lsValue === 'object') {
            localStorage.setItem(this.storagePrefix + lsKey, JSON.stringify(lsValue));
        }
        else {
            localStorage.setItem(this.storagePrefix + lsKey, lsValue);
        }
    }
    removeItem(lsKey) {
        localStorage.removeItem(this.storagePrefix + lsKey);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LocalStorageService, deps: [{ token: ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LocalStorageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LocalStorageService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: ConfigService }] });

class SessionStorageService {
    constructor(configService) {
        this.configService = configService;
        this.storagePrefix = this.configService.getConfig().storagePrefix;
    }
    getItem(lsKey) {
        const lsVal = sessionStorage.getItem(this.storagePrefix + lsKey) || '';
        return UtilsService.checkJSON(lsVal) ? JSON.parse(lsVal) : Number.isNaN(Number(lsVal)) ? lsVal : Number(lsVal);
    }
    getItems(searchString) {
        const tempResults = [];
        for (const key in sessionStorage) {
            if (sessionStorage.hasOwnProperty(key)) {
                if (key.indexOf(searchString) > -1) {
                    if (UtilsService.checkJSON(sessionStorage[key])) {
                        tempResults.push(JSON.parse(sessionStorage[key]));
                    }
                    else {
                        tempResults.push(sessionStorage[key]);
                    }
                }
            }
        }
        return tempResults;
    }
    setItem(lsKey, lsValue) {
        if (typeof lsValue === 'object') {
            sessionStorage.setItem(this.storagePrefix + lsKey, JSON.stringify(lsValue));
        }
        else {
            sessionStorage.setItem(this.storagePrefix + lsKey, lsValue);
        }
    }
    removeItem(lsKey) {
        sessionStorage.removeItem(this.storagePrefix + lsKey);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SessionStorageService, deps: [{ token: ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SessionStorageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SessionStorageService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: ConfigService }] });

class OktaService {
    constructor(configService, lsService, router, ssService) {
        this.configService = configService;
        this.lsService = lsService;
        this.router = router;
        this.ssService = ssService;
        this.LS_ACTIVEROUTE = 'activeRoute';
        this.SS_ERROR = 'oktaError';
        this.oktaError = null;
        this.oktaError$ = new BehaviorSubject(null);
        this.oktaUserInfo = new OktaUserModel({});
        this.oktaUserInfo$ = new ReplaySubject(1);
        this.onDestroy$ = new Subject();
        this.oktaClientConfig = this.setConfig();
        // CLIENT, TOKENPARAMS AND TOKENMANAGER
        this.oktaClient = new OktaAuth(this.oktaClientConfig);
        this.oktaClient.start(); // as of v5, needs to be started as a service to auto-renew
        this.tokenParams = { scopes: this.oktaClientConfig.scopes };
        this.tokenManager = this.oktaClient.tokenManager;
        this.tokenManager.on('error', (error) => {
            // auto-renew failed, usually cuz user deleted cookies or something (no more valid okta session), so sign out
            console.log(error);
            this.oktaClient.signOut({ postLogoutRedirectUri: null }).catch((err) => console.log(err));
        });
        // SUBSCRIBE TO ROUTING
        this.onRouting();
    }
    ngOnDestroy() {
        this.onDestroy$.next();
        this.onDestroy$.complete();
    }
    // ********************************************************************************************************
    // GENERIC STUFF
    // ********************************************************************************************************
    setConfig() {
        const spaasConfig = this.configService.getConfig();
        if (!spaasConfig?.oktaConfig) {
            throw new Error('please provide a valid Okta configuration via the "forRoot" method of the SpaasModule');
        }
        if (spaasConfig?.oktaConfig?.url?.slice(-1) === '/') {
            throw new Error('the okta url should not have a trailing slash');
        }
        if (spaasConfig?.oktaConfig?.tenantId.includes('/')) {
            throw new Error('the okta tenant id should not contain slashes');
        }
        return {
            clientId: spaasConfig.oktaConfig.clientId,
            issuer: spaasConfig.oktaConfig.url + '/oauth2/' + spaasConfig.oktaConfig.tenantId,
            pkce: true,
            redirectUri: spaasConfig.oktaConfig.withPath ? window.location.origin + window.location.pathname : window.location.origin,
            responseType: ['id_token', 'token'],
            scopes: ['openid', 'email'].concat(spaasConfig.oktaConfig.additionalScopes || []),
            tokenManager: {
                storage: 'sessionStorage',
                storageKey: spaasConfig.storagePrefix + 'tokens',
                expireEarlySeconds: 300
            },
            transactionManager: {
                saveNonceCookie: false,
                saveParamsCookie: false,
                saveStateCookie: false,
            },
        };
    }
    onRouting() {
        this.router.events
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((event) => {
            if (event instanceof NavigationStart) {
                // set active route here, so we know where to route to after token redirection
                if (event.url !== '/') {
                    this.setActiveRoute(event.url);
                }
                // BECAUSE WE HANDLE THE CALLBACK BEFORE ROUTING, THE HIDDEN IFRAME REMAINS EMPTY
                this.handleRedirect();
            }
        });
    }
    // ********************************************************************************************************
    // OKTA STUFF
    // ********************************************************************************************************
    handleRedirect() {
        if (this.oktaClient.token.isLoginRedirect() || window.location.search.includes('error=')) {
            // IS REDIRECT OR OKTA ERROR
            this.updateOktaError(null);
            this.parseFromUrl();
        }
        else if (!this.oktaError) {
            // IS REGULAR NAVIGATION: CHECK USER INFO
            this.getUserInfoFromToken();
        }
    }
    parseFromUrl() {
        this.oktaClient.token.parseFromUrl()
            .then((tokenResponse) => {
            this.tokenManager.setTokens(tokenResponse.tokens);
            // NOW SET USER INFO FROM THE TOKEN
            // IT'S THE USER INFO OBSERVABLE THAT OTHER COMPONENTS OR SERVICES SHOULD USE AS INDICATION THAT ALL IS GOOD TO GO
            this.getUserInfoFromToken();
        })
            .catch((err) => {
            this.updateOktaError(err);
        });
    }
    getUserInfoFromToken() {
        if (this.oktaUserInfo.email) {
            return;
        }
        this.tokenManager.getTokens()
            .then((tokens) => {
            this.newUserInfo(tokens?.accessToken?.claims);
            // set a default url. If it exists, fine, if not, it will force the configured redirects to kick in
            this.router.navigate([this.getActiveRoute() || '/home']);
        })
            .catch(() => {
            this.getTokenWithRedirect();
        });
    }
    getTokenWithRedirect() {
        this.oktaClient.token.getWithRedirect(this.tokenParams)
            .catch((e) => console.log(e));
    }
    getCachedAccessToken() {
        // TO BE USED IN CANACTIVE AND/OR CANLOAD AND/OR HTTP INTERCEPTOR
        if (this.oktaClient && this.tokenManager) {
            return this.oktaClient.getAccessToken() || '';
        }
        else {
            console.log('should never happen: tokenmanager is null! Nothing left to do but redirect');
            this.getTokenWithRedirect();
            return '';
        }
    }
    updateOktaError(newState) {
        this.oktaError = newState;
        this.ssService.setItem(this.SS_ERROR, this.oktaError);
        this.newOktaError();
    }
    forceRetry() {
        // METHOD THAT CAN BE CALLED BY WHICHEVER COMPONENT YOU HAVE TO HANDLE/DISPLAY OKTA ERRORS
        // FOR EXAMPLE ON A BUTTON CLICK 'TRY AGAIN' SO USER CAN FORCE AN OKTA RETRY
        this.updateOktaError(null);
        this.getTokenWithRedirect();
    }
    setActiveRoute(url) {
        this.lsService.setItem(this.LS_ACTIVEROUTE, url);
    }
    getActiveRoute() {
        return this.lsService.getItem(this.LS_ACTIVEROUTE) || '';
    }
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newUserInfo(userInfo) {
        this.oktaUserInfo = new OktaUserModel(userInfo);
        this.oktaUserInfo$.next(this.oktaUserInfo);
    }
    onNewUserInfo() {
        return this.oktaUserInfo$.asObservable();
    }
    getUserInfo() {
        return UtilsService.copy(this.oktaUserInfo);
    }
    newOktaError() {
        this.oktaError$.next(this.oktaError);
    }
    onNewOktaError() {
        return this.oktaError$.asObservable();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaService, deps: [{ token: ConfigService }, { token: LocalStorageService }, { token: i3.Router }, { token: SessionStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: ConfigService }, { type: LocalStorageService }, { type: i3.Router }, { type: SessionStorageService }] });

const BG_LIST = {
    employee_solar: { url: './assets/images/bgs/employee_solar', alt: 'Employee at a solar plant' },
    kathu_mirrors: {
        url: './assets/images/bgs/kathu_mirrors',
        alt: 'Cylindro-parabolic mirrors of Kathu Solar Park in South Africa'
    },
    outeiro_ccgt: {
        url: './assets/images/bgs/outeiro_ccgt',
        alt: 'Portugal Tapada do Outeiro combined cycle gas turbine power station'
    },
    shem_mareges: { url: './assets/images/bgs/shem_mareges', alt: 'SHEM Mareges hydro station' },
    shem_thues: { url: './assets/images/bgs/shem_thues', alt: 'SHEM Thues hydro dam' },
    tarfaya_windfarm: { url: './assets/images/bgs/tarfaya_windfarm', alt: 'The Tarfaya wind farm' },
};

class BgComponent extends BaseComponent {
    constructor() {
        super(...arguments);
        this.imgExt = '.webp';
        this.imgList = BG_LIST;
        // LEFT: ALIGN BG IMG LEFT INSTEAD OF DEFAULT RIGHT
        // PORTRAIT: SWITCHES BACKGROUND-SIZE FROM COVER TO AUTO (SO PORTRAIT IMGS ARE NOT STRETCHED OVER FULL WIDTH OF SCREEN)
        this.bgX = 100;
        this.bgY = 50;
        this.bgPortrait = false;
        this.bgImg = 'employee_solar';
        this.bgAnimate = true;
    }
    ngOnInit() {
        this.bg = this.imgList[this.bgImg];
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BgComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: BgComponent, selector: "spaas-bg", inputs: { bgX: "bgX", bgY: "bgY", bgPortrait: "bgPortrait", bgImg: "bgImg", bgAnimate: "bgAnimate" }, usesInheritance: true, ngImport: i0, template: "<div class=\"bg\">\r\n  <div class=\"bg__img-wrapper\"\r\n       [title]=\"bg.alt\"\r\n       [class.with-anim]=\"bgAnimate\"\r\n       [style.background-position-x.%]=\"bgX\"\r\n       [style.background-position-y.%]=\"bgY\"\r\n       [class.portrait]=\"bgPortrait\"\r\n       [style.background-image]=\"'url(' + bg.url + imgExt + ')'\">\r\n  </div>\r\n</div>\r\n", styles: [".bg{height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:-1}.bg__img-wrapper{background-repeat:no-repeat;background-size:cover;height:100%;overflow:hidden;width:100%}.bg__img-wrapper.with-anim{animation:kenburns-bottom 4s ease-out both}.bg__img-wrapper.visible{opacity:1}.bg__img-wrapper.invisible{opacity:0}.bg__img-wrapper.portrait{background-size:auto;left:0;right:auto;width:60%}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.bg__img-wrapper.portrait{width:100%}}@keyframes kenburns-bottom{0%{transform:scale(1) translate(0);transform-origin:14% 14%}to{transform:scale(1.04) translate(-14px,-4px);transform-origin:top left}}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BgComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-bg', template: "<div class=\"bg\">\r\n  <div class=\"bg__img-wrapper\"\r\n       [title]=\"bg.alt\"\r\n       [class.with-anim]=\"bgAnimate\"\r\n       [style.background-position-x.%]=\"bgX\"\r\n       [style.background-position-y.%]=\"bgY\"\r\n       [class.portrait]=\"bgPortrait\"\r\n       [style.background-image]=\"'url(' + bg.url + imgExt + ')'\">\r\n  </div>\r\n</div>\r\n", styles: [".bg{height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:-1}.bg__img-wrapper{background-repeat:no-repeat;background-size:cover;height:100%;overflow:hidden;width:100%}.bg__img-wrapper.with-anim{animation:kenburns-bottom 4s ease-out both}.bg__img-wrapper.visible{opacity:1}.bg__img-wrapper.invisible{opacity:0}.bg__img-wrapper.portrait{background-size:auto;left:0;right:auto;width:60%}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.bg__img-wrapper.portrait{width:100%}}@keyframes kenburns-bottom{0%{transform:scale(1) translate(0);transform-origin:14% 14%}to{transform:scale(1.04) translate(-14px,-4px);transform-origin:top left}}\n"] }]
        }], propDecorators: { bgX: [{
                type: Input
            }], bgY: [{
                type: Input
            }], bgPortrait: [{
                type: Input
            }], bgImg: [{
                type: Input
            }], bgAnimate: [{
                type: Input
            }] } });

class IntroComponent extends BaseComponent {
    constructor(configService, embedModeService, oktaService) {
        super();
        this.configService = configService;
        this.embedModeService = embedModeService;
        this.oktaService = oktaService;
        this.introText = 'all good, loading your data';
        this.checkingAccessText = 'checking your access';
        this.tryAgainButtonTitle = 'try again';
        this.contactGuardButtonTitle = 'contact guard';
        this.goToSnowButtonTitle = 'request access in Snow';
        this.bgImg = 'employee_solar';
        this.isDone = false;
        this.introDone = new EventEmitter();
        this.oktaError = null;
        this.userReceived = false;
        this.isIframe = false;
        this.config = this.configService.getConfig();
        this.isIframe = this.embedModeService.getEmbedMode().isIframe();
        this.onUserInfo();
        this.onOktaError();
    }
    onUserInfo() {
        this.oktaService.onNewUserInfo()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((user) => {
            if (user?.email) {
                this.userReceived = true;
                // emit that all is well, so the screen can already start rendering
                this.introDone.emit(true);
                // and only hide the okta itself after n ms
                timer(1400)
                    .pipe(takeUntil(this.onDestroy$))
                    .subscribe(() => {
                    this.isDone = true;
                });
            }
        });
    }
    onOktaError() {
        this.oktaService.onNewOktaError()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((error) => {
            this.oktaError = error;
        });
    }
    oktaTryAgain() {
        this.oktaService.forceRetry();
    }
    contactGuard() {
        const body = 'Following error was received trying to sign in to ' + this.config?.cleanAppName + ':\r\n\r\n' +
            JSON.stringify(this.oktaError);
        window.location.href = `mailto:5939@engie.com?subject=Okta sign-in error for ${this.config?.cleanAppName}&body=${encodeURIComponent(body)}`;
    }
    goToSnow() {
        window.open('https://gemprod.service-now.com/gem', '_blank');
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IntroComponent, deps: [{ token: ConfigService }, { token: EmbedModeService }, { token: OktaService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: IntroComponent, selector: "spaas-okta-intro", inputs: { introText: "introText", checkingAccessText: "checkingAccessText", tryAgainButtonTitle: "tryAgainButtonTitle", contactGuardButtonTitle: "contactGuardButtonTitle", goToSnowButtonTitle: "goToSnowButtonTitle", bgImg: "bgImg" }, outputs: { introDone: "introDone" }, usesInheritance: true, ngImport: i0, template: "@if (!isDone) {\r\n  <div [class.in-iframe]=\"isIframe\"\r\n       class=\"intro\">\r\n    @if (!isIframe) {\r\n      <div class=\"half-screen flex col center\">\r\n        <!-- LOGO -->\r\n        <div class=\"half-screen__logo flex center\">\r\n          <svg viewBox=\"0 0 512 256\">\r\n            <use [attr.xlink:href]=\"'../../assets/images/logo-engie.svg#svg1'\"></use>\r\n          </svg>\r\n        </div>\r\n        @if (oktaError) {\r\n          <!-- HAS OKTA ERROR -->\r\n          <div class=\"txt-center\">\r\n            <div class=\"txt-bold\">Bumped into an error:</div>\r\n            <div>{{ oktaError.message }}</div>\r\n            <div class=\"flex center pad-big-top column-gap-10\">\r\n              <button (click)=\"oktaTryAgain()\" class=\"primary\">\r\n                {{ tryAgainButtonTitle }}\r\n              </button>\r\n              @if ((oktaError.errorCode | lowercase) === 'access_denied') {\r\n                <button (click)=\"goToSnow()\" class=\"error\">\r\n                  {{ goToSnowButtonTitle }}\r\n                </button>\r\n              } @else {\r\n                <button (click)=\"contactGuard()\" class=\"error\">\r\n                  {{ contactGuardButtonTitle }}\r\n                </button>\r\n              }\r\n            </div>\r\n          </div>\r\n        } @else {\r\n          <!-- NO OKTA ERROR -->\r\n          <div class=\"txt-center pad-big-bottom\">\r\n            <div class=\"pad-big-bottom\">\r\n              {{ userReceived ? introText : checkingAccessText }}\r\n            </div>\r\n            <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n          </div>\r\n        }\r\n      </div>\r\n      <spaas-bg [bgImg]=\"bgImg\"></spaas-bg>\r\n    } @else {\r\n      <div>\r\n        loading embedded {{ config.cleanAppName }}\r\n        <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n      </div>\r\n    }\r\n  </div>\r\n}\r\n", styles: [".intro{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);height:100vh;left:0;position:fixed;top:0;width:100%;z-index:9999}.intro.in-iframe{display:flex;flex-flow:column;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:18px;justify-content:center;text-align:center}.intro.in-iframe>div{margin:auto;width:344px}\n"], dependencies: [{ kind: "component", type: i4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: BgComponent, selector: "spaas-bg", inputs: ["bgX", "bgY", "bgPortrait", "bgImg", "bgAnimate"] }, { kind: "pipe", type: i6.LowerCasePipe, name: "lowercase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: IntroComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-okta-intro', template: "@if (!isDone) {\r\n  <div [class.in-iframe]=\"isIframe\"\r\n       class=\"intro\">\r\n    @if (!isIframe) {\r\n      <div class=\"half-screen flex col center\">\r\n        <!-- LOGO -->\r\n        <div class=\"half-screen__logo flex center\">\r\n          <svg viewBox=\"0 0 512 256\">\r\n            <use [attr.xlink:href]=\"'../../assets/images/logo-engie.svg#svg1'\"></use>\r\n          </svg>\r\n        </div>\r\n        @if (oktaError) {\r\n          <!-- HAS OKTA ERROR -->\r\n          <div class=\"txt-center\">\r\n            <div class=\"txt-bold\">Bumped into an error:</div>\r\n            <div>{{ oktaError.message }}</div>\r\n            <div class=\"flex center pad-big-top column-gap-10\">\r\n              <button (click)=\"oktaTryAgain()\" class=\"primary\">\r\n                {{ tryAgainButtonTitle }}\r\n              </button>\r\n              @if ((oktaError.errorCode | lowercase) === 'access_denied') {\r\n                <button (click)=\"goToSnow()\" class=\"error\">\r\n                  {{ goToSnowButtonTitle }}\r\n                </button>\r\n              } @else {\r\n                <button (click)=\"contactGuard()\" class=\"error\">\r\n                  {{ contactGuardButtonTitle }}\r\n                </button>\r\n              }\r\n            </div>\r\n          </div>\r\n        } @else {\r\n          <!-- NO OKTA ERROR -->\r\n          <div class=\"txt-center pad-big-bottom\">\r\n            <div class=\"pad-big-bottom\">\r\n              {{ userReceived ? introText : checkingAccessText }}\r\n            </div>\r\n            <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n          </div>\r\n        }\r\n      </div>\r\n      <spaas-bg [bgImg]=\"bgImg\"></spaas-bg>\r\n    } @else {\r\n      <div>\r\n        loading embedded {{ config.cleanAppName }}\r\n        <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n      </div>\r\n    }\r\n  </div>\r\n}\r\n", styles: [".intro{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);height:100vh;left:0;position:fixed;top:0;width:100%;z-index:9999}.intro.in-iframe{display:flex;flex-flow:column;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:18px;justify-content:center;text-align:center}.intro.in-iframe>div{margin:auto;width:344px}\n"] }]
        }], ctorParameters: () => [{ type: ConfigService }, { type: EmbedModeService }, { type: OktaService }], propDecorators: { introText: [{
                type: Input
            }], checkingAccessText: [{
                type: Input
            }], tryAgainButtonTitle: [{
                type: Input
            }], contactGuardButtonTitle: [{
                type: Input
            }], goToSnowButtonTitle: [{
                type: Input
            }], bgImg: [{
                type: Input
            }], introDone: [{
                type: Output
            }] } });

class OktaAuthInterceptor {
    static checkUrlsToIntercept(urlsToIntercept, url) {
        for (const curUrl of urlsToIntercept) {
            if (url.startsWith(curUrl)) {
                return true;
            }
        }
        return false;
    }
    constructor(spaasConfig, oktaService) {
        this.spaasConfig = spaasConfig;
        this.oktaService = oktaService;
    }
    intercept(req, next) {
        let headers = req.headers;
        if (req.method !== 'GET') {
            headers = headers.set('Content-type', 'application/json');
        }
        if (req.url.startsWith(this.spaasConfig.oktaConfig.url) ||
            OktaAuthInterceptor.checkUrlsToIntercept(this.spaasConfig.oktaConfig.interceptUrls, req.url)) {
            const token = this.oktaService.getCachedAccessToken();
            headers = headers.set('Authorization', `Bearer ${token}`);
            const authRequest = req.clone({ headers: headers });
            return next.handle(authRequest);
        }
        else {
            const authRequest = req.clone();
            return next.handle(authRequest);
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaAuthInterceptor, deps: [{ token: SpaasConfigModel }, { token: OktaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaAuthInterceptor, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaAuthInterceptor, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: SpaasConfigModel, decorators: [{
                    type: Inject,
                    args: [SpaasConfigModel]
                }] }, { type: OktaService }] });

/**
 * Settings model, used by the settings component to store data on user settings and preferences
 *
 * @property {boolean} dark the application theme, defaults to light
 * @property {ExportExtensionType} exportExtension the preferred extension for data exports, either xlsx or csv
 * @property {DecimalSeparatorType} decimalSeparator the user's decimal separator in Excel, used for exporting and
 * importing data
 * @property {any} extraData any extra data that you want the user to set and store via the settings component
 */
class SettingsModel {
    constructor(objIn) {
        this.dark = objIn.hasOwnProperty('dark') ? objIn.dark : false; // if you update the default, also update material.scss default!!
        this.decimalSeparator = objIn.decimalSeparator || 'dot';
        this.exportExtension = objIn.exportExtension || 'xlsx';
        this.extraData = objIn.extraData || {};
    }
    getCsvDelimiter() {
        return this.decimalSeparator === 'comma' ? ';' : ',';
    }
}

class SettingsService {
    constructor(lsService) {
        this.lsService = lsService;
        this.LS_SETTINGS = 'settings';
        this.settings$ = new BehaviorSubject(new SettingsModel(this.lsService.getItem(this.LS_SETTINGS) || {}));
    }
    // ********************************************************************************************************
    // LOAD DATA
    // ********************************************************************************************************
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newSettings(settings) {
        this.lsService.setItem(this.LS_SETTINGS, settings);
        this.settings$.next(settings);
    }
    onNewSettings() {
        return this.settings$.asObservable();
    }
    getSettings() {
        return this.settings$.getValue();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SettingsService, deps: [{ token: LocalStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SettingsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SettingsService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: LocalStorageService }] });

const DATA__HAS_MENU = { menu: 'yes' };
const DATA__THEME_DARK = { theme: 'dark' };
const DATA__THEME_LIGHT = { theme: 'light' };
class ThemeModel {
    constructor(name, props) {
        this.name = name;
        this.properties = props;
    }
    getRgb(color, alpha = 1) {
        const h = Number(this.properties['--' + color + '-h']);
        let s = Number(this.properties['--' + color + '-s'].replace('%', ''));
        let l = Number(this.properties['--' + color + '-l'].replace('%', ''));
        // Must be fractions of 1
        s /= 100;
        l /= 100;
        const c = (1 - Math.abs(2 * l - 1)) * s, x = c * (1 - Math.abs((h / 60) % 2 - 1)), m = l - c / 2;
        let r = 0, g = 0, b = 0;
        if (0 <= h && h < 60) {
            r = c;
            g = x;
            b = 0;
        }
        else if (60 <= h && h < 120) {
            r = x;
            g = c;
            b = 0;
        }
        else if (120 <= h && h < 180) {
            r = 0;
            g = c;
            b = x;
        }
        else if (180 <= h && h < 240) {
            r = 0;
            g = x;
            b = c;
        }
        else if (240 <= h && h < 300) {
            r = x;
            g = 0;
            b = c;
        }
        else if (300 <= h && h < 360) {
            r = c;
            g = 0;
            b = x;
        }
        r = Math.round((r + m) * 255);
        g = Math.round((g + m) * 255);
        b = Math.round((b + m) * 255);
        return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
    }
}
// THEMES
// IMPORTANT: IF YOU UPDATE THE SETTINGS FOR PRIMARY, ACCENT OR ERROR HERE,
// ALSO UPDATE THEM IN MATERIAL.SCSS !
const light = new ThemeModel('light', {
    '--primary-h': 204,
    '--primary-s': '100%',
    '--primary-l': '40%',
    '--primary-op-min': 0.8,
    '--primary-op-max': 0.4,
    '--secondary-h': 27,
    '--secondary-s': '93%',
    '--secondary-l': '58%',
    '--secondary-op-min': 0.8,
    '--secondary-op-max': 0.4,
    '--accent-h': 144,
    '--accent-s': '100%',
    '--accent-l': '27%',
    '--accent-op-min': 0.95,
    '--accent-op-max': 0.4,
    '--error-h': 1,
    '--error-s': '70%',
    '--error-l': '53%',
    '--error-op-min': 0.6,
    '--error-op-max': 0.4,
    '--bg-h': 0,
    '--bg-s': '0%',
    '--bg-l': '98%',
    '--bg-accent': '-6%',
    '--bg-lighten': '6%',
    '--bg-darken': '-14%',
    '--bg-op-overlay': 0.4,
    '--bg-op-min': 0.84,
    '--bg-op-max': 0.2,
    '--color-h': 0,
    '--color-s': '0%',
    '--color-l': '13.4%',
    '--color-op-min': 0.8,
    '--color-op-max': 0.4,
    '--disabled-h': 0,
    '--disabled-s': '0%',
    '--disabled-l': '62%',
    '--disabled-op-min': 0.8,
    '--disabled-op-max': 0.4,
    '--table-even': '-8%',
    '--table-odd': '-3%',
    '--hover-lighten': '-12%',
});
// IMPORTANT: IF YOU UPDATE THE SETTINGS FOR PRIMARY, ACCENT OR ERROR HERE,
// ALSO UPDATE THEM IN MATERIAL.SCSS !
const dark = new ThemeModel('dark', {
    '--primary-h': 200,
    '--primary-s': '75%',
    '--primary-l': '55%',
    '--primary-op-min': 0.8,
    '--primary-op-max': 0.4,
    '--secondary-h': 27,
    '--secondary-s': '93%',
    '--secondary-l': '58%',
    '--secondary-op-min': 0.8,
    '--secondary-op-max': 0.4,
    '--accent-h': 136,
    '--accent-s': '80%',
    '--accent-l': '38%',
    '--accent-op-min': 0.95,
    '--accent-op-max': 0.4,
    '--error-h': 1,
    '--error-s': '70%',
    '--error-l': '56%',
    '--error-op-min': 0.6,
    '--error-op-max': 0.4,
    '--bg-h': 210,
    '--bg-s': '16%',
    '--bg-l': '10%',
    '--bg-accent': '10%',
    '--bg-lighten': '4%',
    '--bg-darken': '-8%',
    '--bg-op-overlay': 0.4,
    '--bg-op-min': 0.84,
    '--bg-op-max': 0.2,
    '--color-h': 0,
    '--color-s': '0%',
    '--color-l': '98%',
    '--color-op-min': 0.8,
    '--color-op-max': 0.4,
    '--disabled-h': 0,
    '--disabled-s': '0%',
    '--disabled-l': '49.4%',
    '--disabled-op-min': 0.8,
    '--disabled-op-max': 0.4,
    '--table-even': '10%',
    '--table-odd': '3%',
    '--hover-lighten': '22%',
});

class ThemeService {
    constructor(settingsService) {
        this.settingsService = settingsService;
        this.activeTheme = new ThemeModel('', {});
        this.activeTheme$ = new ReplaySubject(1);
    }
    // initTheme is called from the app-init.service
    initTheme() {
        if (!this.activeTheme?.name) {
            this.setActiveTheme(this.settingsService.getSettings().dark ? 'dark' : 'light');
        }
    }
    toggleTheme() {
        if (this.activeTheme?.name === 'light') {
            this.setActiveTheme('dark');
        }
        else {
            this.setActiveTheme('light');
        }
    }
    setActiveTheme(theme) {
        // console.log('setting theme to ' + theme);
        this.activeTheme = theme === 'dark' ? dark : light;
        this.setCssVariables(this.activeTheme.properties);
        this.setBodyData(theme === 'dark' ? DATA__THEME_DARK : DATA__THEME_LIGHT);
        this.newTheme();
    }
    setCssVariables(props) {
        for (const prop in props) {
            if (props.hasOwnProperty(prop)) {
                document.documentElement.style.setProperty(prop, props[prop]);
            }
        }
    }
    setBodyData(props) {
        for (const prop in props) {
            if (props.hasOwnProperty(prop)) {
                document.body.dataset[prop] = props[prop];
            }
        }
    }
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newTheme() {
        this.activeTheme$.next(this.activeTheme);
    }
    onNewActiveTheme() {
        return this.activeTheme$.asObservable();
    }
    getActiveTheme() {
        return this.activeTheme;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ThemeService, deps: [{ token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ThemeService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ThemeService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: SettingsService }] });

/**
 * The toggle component provides a custom toggle-look for checkboxes,
 * in line with the Fluid UI theming.
 */
class ToggleComponent extends BaseComponent {
    constructor() {
        super();
        /** The boolean form control to bind to the toggle (checkbox) */
        this.ctrl = new FormControl(false, { nonNullable: true });
        /**
         * The unique id to reference the input with (necessary for label binding). If you have multiple
         *  toggles, like in each row of a table, you'd typically use the for-index for this
         */
        this.id = '';
        /** The label to display next to the toggle (clickable) */
        this.label = '';
        /** The label position, to the left or right of the toggle */
        this.labelPosition = 'right';
        /** Smaller subtext for underneath the label, usually to provide a more detailed description */
        this.subText = '';
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: ToggleComponent, selector: "spaas-toggle", inputs: { ctrl: "ctrl", id: "id", label: "label", labelPosition: "labelPosition", subText: "subText" }, usesInheritance: true, ngImport: i0, template: "<div class=\"flex column-gap-7 width-fit-content\"\r\n     [ngClass]=\"labelPosition === 'right' ? 'row' : 'row-reverse txt-right'\">\r\n\r\n  <input type=\"checkbox\"\r\n         class=\"tgl tgl-flat\"\r\n         [formControl]=\"ctrl\"\r\n         [id]=\"'toggle_' + id\">\r\n  <label [for]=\"'toggle_' + id\" class=\"tgl-btn\"></label>\r\n\r\n  @if (label) {\r\n    <label [for]=\"'toggle_' + id\">\r\n      {{ label }}\r\n      @if (subText) {\r\n        <div class=\"tgl-subtxt\">\r\n          {{ subText }}\r\n        </div>\r\n      }\r\n    </label>\r\n  }\r\n\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ToggleComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-toggle', template: "<div class=\"flex column-gap-7 width-fit-content\"\r\n     [ngClass]=\"labelPosition === 'right' ? 'row' : 'row-reverse txt-right'\">\r\n\r\n  <input type=\"checkbox\"\r\n         class=\"tgl tgl-flat\"\r\n         [formControl]=\"ctrl\"\r\n         [id]=\"'toggle_' + id\">\r\n  <label [for]=\"'toggle_' + id\" class=\"tgl-btn\"></label>\r\n\r\n  @if (label) {\r\n    <label [for]=\"'toggle_' + id\">\r\n      {{ label }}\r\n      @if (subText) {\r\n        <div class=\"tgl-subtxt\">\r\n          {{ subText }}\r\n        </div>\r\n      }\r\n    </label>\r\n  }\r\n\r\n</div>\r\n" }]
        }], ctorParameters: () => [], propDecorators: { ctrl: [{
                type: Input,
                args: [{ required: true }]
            }], id: [{
                type: Input,
                args: [{ required: true }]
            }], label: [{
                type: Input
            }], labelPosition: [{
                type: Input
            }], subText: [{
                type: Input
            }] } });

class SettingsFormModel {
    constructor(settings) {
        this.dark = new FormControl(settings.dark, { nonNullable: true });
        this.decimalSeparator = new FormControl(settings.decimalSeparator, { nonNullable: true });
        this.exportExtension = new FormControl(settings.exportExtension, { nonNullable: true });
    }
}
/**
 * Settings component that you can simply inject in an otherwise empty 'settings' screen.
 * To let the user choose some basic preferences like dark or light theme.
 * The component uses content projection to allow you to add any app-specific settings you want to persist.
 */
class SettingsComponent extends BaseComponent {
    constructor(oktaService, settingsService, themeService) {
        super();
        this.oktaService = oktaService;
        this.settingsService = settingsService;
        this.themeService = themeService;
        this.settingTitle = 'These are your settings';
        this.darkModeButtonTitle = 'dark mode';
        this.darkModeHintText = ' rest your eyes a bit, switch to dark mode';
        this.exportDescriptionText = 'When downloading data, save as';
        this.excelExportRadioText = 'Excel Workbook (.xlsx)';
        this.csvExportRadioText = 'CSV file (.csv)';
        this.decimalSeparatorText = 'Your decimal separator in Excel';
        this.dotRadioText = 'dot';
        this.commaRadioText = 'comma';
        this.user = new OktaUserModel({});
        this.onNewUser();
        this.settings = this.settingsService.getSettings();
        this.settingsForm = new FormGroup(new SettingsFormModel(this.settings));
    }
    onNewUser() {
        this.oktaService.onNewUserInfo()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((user) => {
            this.user = user;
        });
    }
    onToggleTheme() {
        this.updateSettings();
        this.themeService.toggleTheme();
    }
    updateSettings() {
        // update settings with the form values. Leave extraData untouched, not handled by this component
        this.settings.dark = this.settingsForm.controls.dark.value;
        this.settings.decimalSeparator = this.settingsForm.controls.decimalSeparator.value;
        this.settings.exportExtension = this.settingsForm.controls.exportExtension.value;
        // broadcast the new settings
        this.settingsService.newSettings(this.settings);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SettingsComponent, deps: [{ token: OktaService }, { token: SettingsService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SettingsComponent, selector: "spaas-settings", inputs: { settingTitle: "settingTitle", darkModeButtonTitle: "darkModeButtonTitle", darkModeHintText: "darkModeHintText", exportDescriptionText: "exportDescriptionText", excelExportRadioText: "excelExportRadioText", csvExportRadioText: "csvExportRadioText", decimalSeparatorText: "decimalSeparatorText", dotRadioText: "dotRadioText", commaRadioText: "commaRadioText" }, usesInheritance: true, ngImport: i0, template: "<div class=\"settings\">\r\n\r\n  <div class=\"half-screen\"\r\n       [formGroup]=\"settingsForm\">\r\n\r\n    <h3>{{ settingTitle }} {{ user.firstName ? ', ' + (user.firstName | titlecase) : '' }}</h3>\r\n\r\n    <!-- dark mode -->\r\n    <div>\r\n      <spaas-toggle id=\"dark\"\r\n                    [ctrl]=\"settingsForm.controls.dark\"\r\n                    [label]=\"darkModeButtonTitle\"\r\n                    [subText]=\"darkModeHintText\"\r\n                    (change)=\"onToggleTheme()\">\r\n      </spaas-toggle>\r\n    </div>\r\n\r\n    <!-- export type -->\r\n    <div>\r\n      {{ exportDescriptionText }}\r\n      <mat-radio-group aria-label=\"select an export type\"\r\n                       class=\"flex col\"\r\n                       [formControl]=\"settingsForm.controls.exportExtension\"\r\n                       (change)=\"updateSettings()\">\r\n        <mat-radio-button value=\"xlsx\">{{ excelExportRadioText }}</mat-radio-button>\r\n        <mat-radio-button value=\"csv\">{{ csvExportRadioText }}</mat-radio-button>\r\n      </mat-radio-group>\r\n    </div>\r\n\r\n    <!-- decimal separator -->\r\n    <div>\r\n      {{ decimalSeparatorText }}\r\n      <mat-radio-group aria-label=\"select a decimal separator\"\r\n                       class=\"flex col\"\r\n                       [formControl]=\"settingsForm.controls.decimalSeparator\"\r\n                       (change)=\"updateSettings()\">\r\n        <mat-radio-button value=\"dot\">{{ dotRadioText }}</mat-radio-button>\r\n        <mat-radio-button value=\"comma\">{{ commaRadioText }}</mat-radio-button>\r\n      </mat-radio-group>\r\n    </div>\r\n\r\n    <!-- projected content -->\r\n    <div>\r\n      <ng-content></ng-content>\r\n    </div>\r\n\r\n  </div>\r\n\r\n  <spaas-bg bgImg=\"employee_solar\"></spaas-bg>\r\n\r\n</div>\r\n", styles: [".settings{animation:anim-fade-in 1s ease;position:relative}\n"], dependencies: [{ kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i5.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "directive", type: i4$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i4$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: BgComponent, selector: "spaas-bg", inputs: ["bgX", "bgY", "bgPortrait", "bgImg", "bgAnimate"] }, { kind: "component", type: ToggleComponent, selector: "spaas-toggle", inputs: ["ctrl", "id", "label", "labelPosition", "subText"] }, { kind: "pipe", type: i6.TitleCasePipe, name: "titlecase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SettingsComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-settings', template: "<div class=\"settings\">\r\n\r\n  <div class=\"half-screen\"\r\n       [formGroup]=\"settingsForm\">\r\n\r\n    <h3>{{ settingTitle }} {{ user.firstName ? ', ' + (user.firstName | titlecase) : '' }}</h3>\r\n\r\n    <!-- dark mode -->\r\n    <div>\r\n      <spaas-toggle id=\"dark\"\r\n                    [ctrl]=\"settingsForm.controls.dark\"\r\n                    [label]=\"darkModeButtonTitle\"\r\n                    [subText]=\"darkModeHintText\"\r\n                    (change)=\"onToggleTheme()\">\r\n      </spaas-toggle>\r\n    </div>\r\n\r\n    <!-- export type -->\r\n    <div>\r\n      {{ exportDescriptionText }}\r\n      <mat-radio-group aria-label=\"select an export type\"\r\n                       class=\"flex col\"\r\n                       [formControl]=\"settingsForm.controls.exportExtension\"\r\n                       (change)=\"updateSettings()\">\r\n        <mat-radio-button value=\"xlsx\">{{ excelExportRadioText }}</mat-radio-button>\r\n        <mat-radio-button value=\"csv\">{{ csvExportRadioText }}</mat-radio-button>\r\n      </mat-radio-group>\r\n    </div>\r\n\r\n    <!-- decimal separator -->\r\n    <div>\r\n      {{ decimalSeparatorText }}\r\n      <mat-radio-group aria-label=\"select a decimal separator\"\r\n                       class=\"flex col\"\r\n                       [formControl]=\"settingsForm.controls.decimalSeparator\"\r\n                       (change)=\"updateSettings()\">\r\n        <mat-radio-button value=\"dot\">{{ dotRadioText }}</mat-radio-button>\r\n        <mat-radio-button value=\"comma\">{{ commaRadioText }}</mat-radio-button>\r\n      </mat-radio-group>\r\n    </div>\r\n\r\n    <!-- projected content -->\r\n    <div>\r\n      <ng-content></ng-content>\r\n    </div>\r\n\r\n  </div>\r\n\r\n  <spaas-bg bgImg=\"employee_solar\"></spaas-bg>\r\n\r\n</div>\r\n", styles: [".settings{animation:anim-fade-in 1s ease;position:relative}\n"] }]
        }], ctorParameters: () => [{ type: OktaService }, { type: SettingsService }, { type: ThemeService }], propDecorators: { settingTitle: [{
                type: Input
            }], darkModeButtonTitle: [{
                type: Input
            }], darkModeHintText: [{
                type: Input
            }], exportDescriptionText: [{
                type: Input
            }], excelExportRadioText: [{
                type: Input
            }], csvExportRadioText: [{
                type: Input
            }], decimalSeparatorText: [{
                type: Input
            }], dotRadioText: [{
                type: Input
            }], commaRadioText: [{
                type: Input
            }] } });

class PreloaderService {
    constructor() {
        this.preloaderMsgs = [];
        this.preloaderMsgs$ = new BehaviorSubject([]);
    }
    // ********************************************************************************************************
    // SAVE DATA
    // ********************************************************************************************************
    /**
     * Activates the preloader overlay ("<spaas-preloader>" to be added to your app.component.html).
     *
     * @param preloaderMsg will be added to the list of messages, to be shown as feedback to the user.
     */
    start(preloaderMsg) {
        this.preloaderMsgs.push(preloaderMsg);
        this.newPreloaderMsg();
    }
    /**
     * Removes the "preloaderMsg" from the list of preloader messages.
     *
     * @param preloaderMsg message to be removed from the list. If the "preloaderMsg" was the last one on the list,
     * the preloader overlay will be hidden.
     */
    stop(preloaderMsg) {
        this.preloaderMsgs = this.preloaderMsgs.filter((l) => l !== preloaderMsg);
        this.newPreloaderMsg();
    }
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newPreloaderMsg() {
        this.preloaderMsgs$.next(this.preloaderMsgs);
    }
    onNewPreloaderMsg() {
        return this.preloaderMsgs$.asObservable();
    }
    getPreloaderMsgs() {
        return JSON.parse(JSON.stringify(this.preloaderMsgs$.getValue()));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreloaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreloaderService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreloaderService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }] });

class PreloaderComponent extends BaseComponent {
    constructor(preloaderService) {
        super();
        this.preloaderService = preloaderService;
        this.isActive = false;
        this.mostRecent = '';
        this.preloaderService.onNewPreloaderMsg()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((msgs) => {
            this.isActive = msgs.length > 0;
            this.mostRecent = msgs[msgs.length - 1] || '';
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreloaderComponent, deps: [{ token: PreloaderService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: PreloaderComponent, selector: "spaas-preloader", usesInheritance: true, ngImport: i0, template: "@if (isActive) {\r\n  <div class=\"preloader\">\r\n    <mat-progress-bar [mode]=\"'indeterminate'\" class=\"preloader__progbar\">\r\n    </mat-progress-bar>\r\n    <div class=\"preloader__text\">\r\n      {{ mostRecent }}\r\n    </div>\r\n  </div>\r\n}\r\n", styles: [".preloader{animation:anim-visible 0s ease forwards;background:hsla(var(--bg-h),var(--bg-s),var(--bg-l),var(--bg-op-overlay));cursor:wait;height:100%;left:0;opacity:0;visibility:hidden;position:fixed;top:0;width:100vw;z-index:9996}.preloader__text{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);font-family:BebasNeue,Lato,Arial,sans-serif;font-size:24px;margin:14px auto;padding:14px;text-align:center;width:fit-content}.preloader__progbar{left:0;position:fixed;top:0;width:100%}\n"], dependencies: [{ kind: "component", type: i4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreloaderComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-preloader', template: "@if (isActive) {\r\n  <div class=\"preloader\">\r\n    <mat-progress-bar [mode]=\"'indeterminate'\" class=\"preloader__progbar\">\r\n    </mat-progress-bar>\r\n    <div class=\"preloader__text\">\r\n      {{ mostRecent }}\r\n    </div>\r\n  </div>\r\n}\r\n", styles: [".preloader{animation:anim-visible 0s ease forwards;background:hsla(var(--bg-h),var(--bg-s),var(--bg-l),var(--bg-op-overlay));cursor:wait;height:100%;left:0;opacity:0;visibility:hidden;position:fixed;top:0;width:100vw;z-index:9996}.preloader__text{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);font-family:BebasNeue,Lato,Arial,sans-serif;font-size:24px;margin:14px auto;padding:14px;text-align:center;width:fit-content}.preloader__progbar{left:0;position:fixed;top:0;width:100%}\n"] }]
        }], ctorParameters: () => [{ type: PreloaderService }] });

/*
const SLIDE_OUTS = {
  dagResults: 'dag-results',
  taskLogs: 'task-logs'
} as const;

export type SlideOutType = typeof SLIDE_OUTS[keyof typeof SLIDE_OUTS];
*/
class SlideOutService {
    constructor() {
        this.soActive$ = new BehaviorSubject('');
    }
    newSlideOut(slideOut) {
        if (slideOut === this.getSlideOut()) {
            slideOut = '';
        }
        this.soActive$.next(slideOut);
    }
    onNewSlideOut() {
        return this.soActive$.asObservable();
    }
    getSlideOut() {
        return this.soActive$.getValue();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }] });

class SlideOutComponent extends BaseComponent {
    constructor(slideOutService) {
        super();
        this.slideOutService = slideOutService;
        this.soActive = '';
        this.getSmActive();
    }
    ngOnDestroy() {
        this.slideOutService.newSlideOut('');
        super.ngOnDestroy();
    }
    // ********************************************************************************************************
    // LOAD DATA
    // ********************************************************************************************************
    getSmActive() {
        this.slideOutService.onNewSlideOut()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((sm) => {
            this.soActive = sm;
        });
    }
    // ********************************************************************************************************
    // UI
    // ********************************************************************************************************
    onClose() {
        this.slideOutService.newSlideOut('');
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutComponent, deps: [{ token: SlideOutService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SlideOutComponent, selector: "spaas-slide-out", usesInheritance: true, ngImport: i0, template: "<div class=\"slide-out\"\r\n     [class.visible]=\"soActive\">\r\n  <div class=\"slide-out__close\"\r\n       [class.visible]=\"soActive\">\r\n    <mat-icon (click)=\"onClose()\">clear</mat-icon>\r\n  </div>\r\n  <ng-content select=\"spaas-slide-out-content\"></ng-content>\r\n</div>\r\n\r\n", styles: [".slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9004}.slide-out.visible{transform:translateZ(0)}.slide-out__close{color:hsla(var(--error-h),var(--error-s),var(--error-l),1);opacity:0;position:fixed;right:54px;top:20px;z-index:9999}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__close{right:10px}}.slide-out__close.visible{animation:rotate .6s;opacity:1}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(90deg)}}.slide-out__close .mat-icon{font-size:28px!important;height:28px!important;line-height:28px!important;width:28px!important}.slide-out__content{animation:anim-fade-in .4s .2s ease forwards;display:flex;height:calc(100vh - 28px);justify-content:flex-start;left:88px;opacity:0;overflow-y:auto;overscroll-behavior:contain;position:fixed;top:14px;width:calc(100% - 176px);z-index:9005}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__content{left:44px;width:calc(100% - 88px)}}\n"], dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-slide-out', template: "<div class=\"slide-out\"\r\n     [class.visible]=\"soActive\">\r\n  <div class=\"slide-out__close\"\r\n       [class.visible]=\"soActive\">\r\n    <mat-icon (click)=\"onClose()\">clear</mat-icon>\r\n  </div>\r\n  <ng-content select=\"spaas-slide-out-content\"></ng-content>\r\n</div>\r\n\r\n", styles: [".slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9004}.slide-out.visible{transform:translateZ(0)}.slide-out__close{color:hsla(var(--error-h),var(--error-s),var(--error-l),1);opacity:0;position:fixed;right:54px;top:20px;z-index:9999}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__close{right:10px}}.slide-out__close.visible{animation:rotate .6s;opacity:1}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(90deg)}}.slide-out__close .mat-icon{font-size:28px!important;height:28px!important;line-height:28px!important;width:28px!important}.slide-out__content{animation:anim-fade-in .4s .2s ease forwards;display:flex;height:calc(100vh - 28px);justify-content:flex-start;left:88px;opacity:0;overflow-y:auto;overscroll-behavior:contain;position:fixed;top:14px;width:calc(100% - 176px);z-index:9005}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__content{left:44px;width:calc(100% - 88px)}}\n"] }]
        }], ctorParameters: () => [{ type: SlideOutService }] });

class SlideOutContentComponent {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SlideOutContentComponent, selector: "spaas-slide-out-content", ngImport: i0, template: "<div class=\"slide-out__content\">\r\n  <ng-content></ng-content>\r\n</div>\r\n", styles: [".slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9004}.slide-out.visible{transform:translateZ(0)}.slide-out__close{color:hsla(var(--error-h),var(--error-s),var(--error-l),1);opacity:0;position:fixed;right:54px;top:20px;z-index:9999}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__close{right:10px}}.slide-out__close.visible{animation:rotate .6s;opacity:1}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(90deg)}}.slide-out__close .mat-icon{font-size:28px!important;height:28px!important;line-height:28px!important;width:28px!important}.slide-out__content{animation:anim-fade-in .4s .2s ease forwards;display:flex;height:calc(100vh - 28px);justify-content:flex-start;left:88px;opacity:0;overflow-y:auto;overscroll-behavior:contain;position:fixed;top:14px;width:calc(100% - 176px);z-index:9005}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__content{left:44px;width:calc(100% - 88px)}}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SlideOutContentComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-slide-out-content', template: "<div class=\"slide-out__content\">\r\n  <ng-content></ng-content>\r\n</div>\r\n", styles: [".slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9004}.slide-out.visible{transform:translateZ(0)}.slide-out__close{color:hsla(var(--error-h),var(--error-s),var(--error-l),1);opacity:0;position:fixed;right:54px;top:20px;z-index:9999}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__close{right:10px}}.slide-out__close.visible{animation:rotate .6s;opacity:1}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(90deg)}}.slide-out__close .mat-icon{font-size:28px!important;height:28px!important;line-height:28px!important;width:28px!important}.slide-out__content{animation:anim-fade-in .4s .2s ease forwards;display:flex;height:calc(100vh - 28px);justify-content:flex-start;left:88px;opacity:0;overflow-y:auto;overscroll-behavior:contain;position:fixed;top:14px;width:calc(100% - 176px);z-index:9005}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__content{left:44px;width:calc(100% - 88px)}}\n"] }]
        }] });

class MaterialModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: MaterialModule, imports: [DragDropModule,
            MatBottomSheetModule,
            MatIconModule,
            MatProgressBarModule,
            MatRadioModule,
            MatSnackBarModule,
            MatTooltipModule], exports: [DragDropModule,
            MatBottomSheetModule,
            MatIconModule,
            MatProgressBarModule,
            MatRadioModule,
            MatSnackBarModule,
            MatTooltipModule] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MaterialModule, providers: [
            {
                provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
                useValue: {
                    subscriptSizing: 'dynamic'
                }
            },
            {
                provide: MAT_RADIO_DEFAULT_OPTIONS,
                useValue: { color: 'primary' },
            }
        ], imports: [DragDropModule,
            MatBottomSheetModule,
            MatIconModule,
            MatProgressBarModule,
            MatRadioModule,
            MatSnackBarModule,
            MatTooltipModule, DragDropModule,
            MatBottomSheetModule,
            MatIconModule,
            MatProgressBarModule,
            MatRadioModule,
            MatSnackBarModule,
            MatTooltipModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MaterialModule, decorators: [{
            type: NgModule,
            args: [{
                    exports: [
                        DragDropModule,
                        MatBottomSheetModule,
                        MatIconModule,
                        MatProgressBarModule,
                        MatRadioModule,
                        MatSnackBarModule,
                        MatTooltipModule,
                    ],
                    imports: [
                        DragDropModule,
                        MatBottomSheetModule,
                        MatIconModule,
                        MatProgressBarModule,
                        MatRadioModule,
                        MatSnackBarModule,
                        MatTooltipModule,
                    ],
                    providers: [
                        {
                            provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
                            useValue: {
                                subscriptSizing: 'dynamic'
                            }
                        },
                        {
                            provide: MAT_RADIO_DEFAULT_OPTIONS,
                            useValue: { color: 'primary' },
                        }
                    ]
                }]
        }] });

class NewVersionComponent extends BaseComponent {
    constructor(bottomSheetRef) {
        super();
        this.bottomSheetRef = bottomSheetRef;
    }
    reload() {
        this.bottomSheetRef.dismiss();
        window.location.reload();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NewVersionComponent, deps: [{ token: i1.MatBottomSheetRef }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: NewVersionComponent, selector: "spaas-new-version", usesInheritance: true, ngImport: i0, template: "<div class=\"txt-center\">\r\n  new version available\r\n  <div class=\"flex center pad-big-top\">\r\n    <button class=\"primary bold\" (click)=\"reload()\">\r\n      load it now\r\n    </button>\r\n  </div>\r\n</div>\r\n", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NewVersionComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-new-version', template: "<div class=\"txt-center\">\r\n  new version available\r\n  <div class=\"flex center pad-big-top\">\r\n    <button class=\"primary bold\" (click)=\"reload()\">\r\n      load it now\r\n    </button>\r\n  </div>\r\n</div>\r\n" }]
        }], ctorParameters: () => [{ type: i1.MatBottomSheetRef }] });

class NewVersionService {
    constructor(spaasConfig, bottomSheet, swUpdate) {
        this.spaasConfig = spaasConfig;
        this.bottomSheet = bottomSheet;
        this.swUpdate = swUpdate;
        // we get the raw spaasConfig provided by the client app, not the one from the ConfigService (because
        // this is called from appInit, so we cannot rely on the NewVersionConfigModel constructor making things clean.
        // Hence, always do a new NewVersionConfigModel
    }
    getNewVersion() {
        // LISTEN FOR NEW VERSIONS
        if (!this.swUpdate?.isEnabled) {
            return;
        }
        this.swUpdate.versionUpdates
            .pipe(filter((evt) => evt.type === 'VERSION_READY'))
            .subscribe(() => {
            const cfg = new NewVersionConfigModel(this.spaasConfig?.newVersionConfig || {});
            this.bottomSheet.open(NewVersionComponent, { hasBackdrop: cfg.hasBackdrop });
            this.startTimer();
        });
    }
    startTimer() {
        const cfg = new NewVersionConfigModel(this.spaasConfig?.newVersionConfig || {});
        if (cfg.reminder && cfg.hasBackdrop) {
            // if reminder is set and hasBackdrop is true, just start the timer (if no backdrop, the pop-up will stay open, no need for a reminder)
            // if the user has accepted the new version anyway, the page will reload
            // and after page reload, the timer will not be started again, because there will no longer be a new version
            timer(cfg.reminder * 60000, cfg.reminder * 60000)
                .subscribe(() => {
                this.bottomSheet.open(NewVersionComponent, { hasBackdrop: cfg.hasBackdrop });
            });
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NewVersionService, deps: [{ token: SpaasConfigModel, optional: true }, { token: i1.MatBottomSheet }, { token: i2$1.SwUpdate }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NewVersionService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NewVersionService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: SpaasConfigModel, decorators: [{
                    type: Optional
                }, {
                    type: Inject,
                    args: [SpaasConfigModel]
                }] }, { type: i1.MatBottomSheet }, { type: i2$1.SwUpdate }] });

class PwaInstallComponent extends BaseComponent {
    constructor(bottomSheetRef, pwaInstallService) {
        super();
        this.bottomSheetRef = bottomSheetRef;
        this.pwaInstallService = pwaInstallService;
    }
    doInstall() {
        this.pwaInstallService.doInstall();
        this.bottomSheetRef.dismiss();
    }
    ignoreInstall() {
        this.pwaInstallService.ignoreInstall();
        this.bottomSheetRef.dismiss();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PwaInstallComponent, deps: [{ token: i1.MatBottomSheetRef }, { token: PwaInstallService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PwaInstallComponent, selector: "spaas-pwa-install", usesInheritance: true, ngImport: i0, template: "<div class=\"txt-center\">\n  install as an app?\n  <div class=\"flex center column-gap-10 pad-big-top\">\n    <button class=\"error bold\" (click)=\"ignoreInstall()\">\n      no thanx\n    </button>\n    <button class=\"primary bold\" (click)=\"doInstall()\">\n      yes please\n    </button>\n  </div>\n</div>\n", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PwaInstallComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-pwa-install', template: "<div class=\"txt-center\">\n  install as an app?\n  <div class=\"flex center column-gap-10 pad-big-top\">\n    <button class=\"error bold\" (click)=\"ignoreInstall()\">\n      no thanx\n    </button>\n    <button class=\"primary bold\" (click)=\"doInstall()\">\n      yes please\n    </button>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.MatBottomSheetRef }, { type: PwaInstallService }] });

class PwaInstallService {
    constructor(bottomSheet, lsService, platform) {
        this.bottomSheet = bottomSheet;
        this.lsService = lsService;
        this.platform = platform;
        this.LS_ALREADY_PROMPTED = 'installPrompted';
    }
    installPrompt() {
        if (!this.platform.IOS) {
            fromEvent(window, 'beforeinstallprompt')
                .subscribe((e) => {
                e.preventDefault();
                this.promptEvent = e;
                this.openBottomSheet();
            });
        }
        else {
            const isInStandaloneMode = ('standalone' in window.navigator) && (window.navigator['standalone']);
            if (!isInStandaloneMode) {
                this.openBottomSheet();
            }
        }
    }
    openBottomSheet() {
        console.log('will prompt install');
        if (this.lsService.getItem(this.LS_ALREADY_PROMPTED) === 'true') {
            return;
        }
        timer(3000)
            .pipe(take(1))
            .subscribe(() => {
            this.bottomSheet.open(PwaInstallComponent);
        });
    }
    doInstall() {
        this.promptEvent.prompt();
    }
    ignoreInstall() {
        this.lsService.setItem(this.LS_ALREADY_PROMPTED, true);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PwaInstallService, deps: [{ token: i1.MatBottomSheet }, { token: LocalStorageService }, { token: i3$1.Platform }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PwaInstallService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PwaInstallService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: i1.MatBottomSheet }, { type: LocalStorageService }, { type: i3$1.Platform }] });

class AppInitService {
    constructor(embedModeService, newVersionService, pwaInstallService, themeService) {
        this.embedModeService = embedModeService;
        this.newVersionService = newVersionService;
        this.pwaInstallService = pwaInstallService;
        this.themeService = themeService;
    }
    // initApp is called from the spaas.module using APP_INITIALIZER
    initApp() {
        this.embedModeService.setEmbedMode();
        this.themeService.initTheme();
        this.pwaInstallService.installPrompt();
        this.newVersionService.getNewVersion();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppInitService, deps: [{ token: EmbedModeService }, { token: NewVersionService }, { token: PwaInstallService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppInitService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AppInitService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: EmbedModeService }, { type: NewVersionService }, { type: PwaInstallService }, { type: ThemeService }] });

class MenuComponent extends BaseComponent {
    constructor(embedModeService, slideOutService, themeService) {
        super();
        this.embedModeService = embedModeService;
        this.slideOutService = slideOutService;
        this.themeService = themeService;
        /** The menu items to render in the DOM. */
        this.menuItems = [];
        this.mmActive = false;
        this.so = '';
        this.isIframe = false;
        this.isIframe = this.embedModeService.getEmbedMode().isIframe();
        if (!this.isIframe) {
            this.themeService.setBodyData(DATA__HAS_MENU);
        }
        this.onSo();
    }
    // ********************************************************************************************************
    // LOAD
    // ********************************************************************************************************
    onSo() {
        this.slideOutService.onNewSlideOut()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((so) => {
            if (so) {
                this.mmActive = false;
            }
        });
    }
    // ********************************************************************************************************
    // UI
    // ********************************************************************************************************
    // EVENT LISTENERS
    onToggleMenu() {
        this.mmActive = !this.mmActive;
        if (this.mmActive) {
            // menu active: close open slide-outs
            this.slideOutService.newSlideOut('');
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuComponent, deps: [{ token: EmbedModeService }, { token: SlideOutService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: MenuComponent, selector: "spaas-menu", inputs: { menuItems: "menuItems" }, usesInheritance: true, ngImport: i0, template: "@if (!isIframe) {\r\n  <div class=\"mm\">\r\n\r\n    <div (click)=\"onToggleMenu()\"\r\n         [class.active]=\"mmActive\"\r\n         class=\"mm__burger\">\r\n      <span></span>\r\n      <span></span>\r\n    </div>\r\n    <div [class.visible]=\"mmActive\"\r\n         class=\"mm__slide-out\">\r\n      @if (mmActive) {\r\n        <div class=\"mm__slide-out__items\">\r\n          @for (item of menuItems; track item) {\r\n            <div (click)=\"onToggleMenu()\"\r\n                 [routerLink]=\"item.rtrLink\"\r\n                 routerLinkActive=\"accent\">\r\n              {{ item.label }}\r\n            </div>\r\n          }\r\n        </div>\r\n        <div class=\"mm__slide-out__logo\">\r\n          <svg viewBox=\"0 0 512 256\">\r\n            <use [attr.xlink:href]=\"'assets/images/logo-engie.svg#svg1'\"></use>\r\n          </svg>\r\n        </div>\r\n      }\r\n    </div>\r\n  </div>\r\n}\r\n", styles: [".mm__burger{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);cursor:pointer;height:44px;left:0;position:fixed;top:2px;transition:background-color .4s;width:44px;z-index:9996}.mm__burger span{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),1);border-radius:9px;display:block;height:3px;opacity:1;position:absolute;right:10px;transform:rotate(0);transition:.25s ease-in-out}.mm__burger span:nth-child(1){top:19px;width:24px}.mm__burger span:nth-child(2){top:24px;width:18px}.mm__burger.active span{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);height:3px}.mm__burger.active span:nth-child(1){top:20px;transform:rotate(45deg);width:24px}.mm__burger.active span:nth-child(2){top:24px;transform:rotate(-45deg);width:24px}.mm__slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;padding:28px 88px;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9995}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.mm__slide-out{padding:28px 44px}}.mm__slide-out.visible{transform:translateZ(0)}.mm__slide-out__items{animation:anim-fade-in .2s .2s forwards;opacity:0}.mm__slide-out__items>div{cursor:pointer;font-size:28px;font-family:BebasNeue,Lato,Arial,sans-serif;padding:7px;transition:transform .2s}.mm__slide-out__items>div:hover{transform:translate(7px)}.mm__slide-out__logo{bottom:14px;color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + -4%),1);height:40vh;position:absolute;right:88px;width:80vh}.mm__slide-out__logo svg{height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-menu', template: "@if (!isIframe) {\r\n  <div class=\"mm\">\r\n\r\n    <div (click)=\"onToggleMenu()\"\r\n         [class.active]=\"mmActive\"\r\n         class=\"mm__burger\">\r\n      <span></span>\r\n      <span></span>\r\n    </div>\r\n    <div [class.visible]=\"mmActive\"\r\n         class=\"mm__slide-out\">\r\n      @if (mmActive) {\r\n        <div class=\"mm__slide-out__items\">\r\n          @for (item of menuItems; track item) {\r\n            <div (click)=\"onToggleMenu()\"\r\n                 [routerLink]=\"item.rtrLink\"\r\n                 routerLinkActive=\"accent\">\r\n              {{ item.label }}\r\n            </div>\r\n          }\r\n        </div>\r\n        <div class=\"mm__slide-out__logo\">\r\n          <svg viewBox=\"0 0 512 256\">\r\n            <use [attr.xlink:href]=\"'assets/images/logo-engie.svg#svg1'\"></use>\r\n          </svg>\r\n        </div>\r\n      }\r\n    </div>\r\n  </div>\r\n}\r\n", styles: [".mm__burger{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);cursor:pointer;height:44px;left:0;position:fixed;top:2px;transition:background-color .4s;width:44px;z-index:9996}.mm__burger span{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),1);border-radius:9px;display:block;height:3px;opacity:1;position:absolute;right:10px;transform:rotate(0);transition:.25s ease-in-out}.mm__burger span:nth-child(1){top:19px;width:24px}.mm__burger span:nth-child(2){top:24px;width:18px}.mm__burger.active span{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);height:3px}.mm__burger.active span:nth-child(1){top:20px;transform:rotate(45deg);width:24px}.mm__burger.active span:nth-child(2){top:24px;transform:rotate(-45deg);width:24px}.mm__slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;padding:28px 88px;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9995}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.mm__slide-out{padding:28px 44px}}.mm__slide-out.visible{transform:translateZ(0)}.mm__slide-out__items{animation:anim-fade-in .2s .2s forwards;opacity:0}.mm__slide-out__items>div{cursor:pointer;font-size:28px;font-family:BebasNeue,Lato,Arial,sans-serif;padding:7px;transition:transform .2s}.mm__slide-out__items>div:hover{transform:translate(7px)}.mm__slide-out__logo{bottom:14px;color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + -4%),1);height:40vh;position:absolute;right:88px;width:80vh}.mm__slide-out__logo svg{height:100%;width:100%}\n"] }]
        }], ctorParameters: () => [{ type: EmbedModeService }, { type: SlideOutService }, { type: ThemeService }], propDecorators: { menuItems: [{
                type: Input
            }] } });

class ActiveRouteModel {
    constructor(url, queryParams, params) {
        this.params = params || {};
        this.queryParams = queryParams || {};
        this.url = url && url.startsWith('/') ? url.replace(/\//g, ' ') : '';
    }
}

class ActiveRouteService {
    constructor(configService, titleService) {
        this.configService = configService;
        this.titleService = titleService;
        this.activeRoute = new ActiveRouteModel('', {}, {});
        this.activeRoute$ = new ReplaySubject(1);
    }
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newActiveRoute(url, queryParams, params) {
        this.activeRoute = new ActiveRouteModel(url, queryParams, params);
        this.titleService.setTitle(this.configService.getConfig().cleanAppName + ' - ' + this.activeRoute.url + ' | Engie');
        this.activeRoute$.next(this.activeRoute);
    }
    onNewActiveRoute() {
        return this.activeRoute$.asObservable();
    }
    getActiveRoute() {
        return this.activeRoute;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActiveRouteService, deps: [{ token: ConfigService }, { token: i2$2.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActiveRouteService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActiveRouteService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: ConfigService }, { type: i2$2.Title }] });

class MenuSideBarComponent extends BaseComponent {
    constructor(activeRouteService, configService, themeService) {
        super();
        this.activeRouteService = activeRouteService;
        this.configService = configService;
        this.themeService = themeService;
        this.titleText = '';
        this.env = '';
        this.fullEnv = '';
        // enable menu gutter and notify parent that iframe has menu
        this.themeService.setBodyData(DATA__HAS_MENU);
        this.setEnv();
    }
    ngOnInit() {
        if (!this.titleText) {
            this.titleText = this.activeRouteService.getActiveRoute()?.url;
        }
    }
    setEnv() {
        const config = this.configService.getConfig();
        if (config.environment &&
            !config.environment.startsWith('local') &&
            !config.environment.startsWith('prod')) {
            this.env = config.environment.slice(0, 3);
            this.fullEnv = config.environment;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuSideBarComponent, deps: [{ token: ActiveRouteService }, { token: ConfigService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: MenuSideBarComponent, selector: "spaas-menu-side-bar", inputs: { titleText: "titleText" }, usesInheritance: true, ngImport: i0, template: "<div class=\"mm-side-bar\">\r\n\r\n  @if (env) {\r\n    <div class=\"mm-side-bar__env {{env}}\"\r\n         matTooltipPosition=\"right\"\r\n         matTooltipClass=\"bg-error\"\r\n         matTooltip=\"you are on the {{fullEnv | uppercase}} environment\">\r\n      {{ env }}\r\n    </div>\r\n  }\r\n\r\n  <div class=\"mm-side-bar__title\">\r\n    {{ titleText }}\r\n  </div>\r\n\r\n  <ng-content select=\"spaas-menu-side-bar-icon\"></ng-content>\r\n\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr}.mm-side-bar__title{min-height:174px;padding:44px 0 7px 2px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}\n"], dependencies: [{ kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i6.UpperCasePipe, name: "uppercase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuSideBarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-menu-side-bar', template: "<div class=\"mm-side-bar\">\r\n\r\n  @if (env) {\r\n    <div class=\"mm-side-bar__env {{env}}\"\r\n         matTooltipPosition=\"right\"\r\n         matTooltipClass=\"bg-error\"\r\n         matTooltip=\"you are on the {{fullEnv | uppercase}} environment\">\r\n      {{ env }}\r\n    </div>\r\n  }\r\n\r\n  <div class=\"mm-side-bar__title\">\r\n    {{ titleText }}\r\n  </div>\r\n\r\n  <ng-content select=\"spaas-menu-side-bar-icon\"></ng-content>\r\n\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr}.mm-side-bar__title{min-height:174px;padding:44px 0 7px 2px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}\n"] }]
        }], ctorParameters: () => [{ type: ActiveRouteService }, { type: ConfigService }, { type: ThemeService }], propDecorators: { titleText: [{
                type: Input
            }] } });

class MenuSideBarIconComponent extends BaseComponent {
    constructor(slideOutService) {
        super();
        this.slideOutService = slideOutService;
        this.tooltipMsg = '';
        this.withTopMargin = false;
        this.withHover = true;
        this.withDivider = false;
        // GENERIC STATE INDICATORS FROM PARENT
        this.isDisabled = false;
        // TYPE TO INDICATE WHAT THIS ICON SHOULD DO WHEN CLICKED
        this.soType = '';
        // MOUSE-EVENT EMITTER IF NOT SO-TYPE
        this.clicked = new EventEmitter();
        this.activeSo = '';
        this.isActive = false;
        this.getSoActive();
    }
    getSoActive() {
        this.slideOutService.onNewSlideOut()
            .pipe(takeUntil(this.onDestroy$))
            .subscribe((so) => {
            this.activeSo = so;
            this.isActive = this.soType !== '' && this.activeSo === this.soType;
        });
    }
    onClick(e) {
        if (this.soType) {
            this.slideOutService.newSlideOut(this.soType);
        }
        else if (!this.isDisabled) {
            this.clicked.emit(e);
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuSideBarIconComponent, deps: [{ token: SlideOutService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MenuSideBarIconComponent, selector: "spaas-menu-side-bar-icon", inputs: { tooltipMsg: "tooltipMsg", withTopMargin: "withTopMargin", withHover: "withHover", withDivider: "withDivider", isDisabled: "isDisabled", soType: "soType" }, outputs: { clicked: "clicked" }, usesInheritance: true, ngImport: i0, template: "<div class=\"mm-side-bar__icon\"\r\n     [style.--margin-top]=\"withTopMargin || withDivider ? '24px' : '0px'\"\r\n     [class.active]=\"isActive\"\r\n     [class.disabled]=\"isDisabled\"\r\n     [class.with-hover]=\"withHover\"\r\n     [class.with-divider]=\"withDivider\"\r\n     [matTooltip]=\"tooltipMsg\"\r\n     matTooltipPosition=\"right\"\r\n     (click)=\"onClick($event)\">\r\n  <ng-content></ng-content>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr}.mm-side-bar__title{min-height:174px;padding:44px 0 7px 2px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}\n"], dependencies: [{ kind: "directive", type: i4$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MenuSideBarIconComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-menu-side-bar-icon', template: "<div class=\"mm-side-bar__icon\"\r\n     [style.--margin-top]=\"withTopMargin || withDivider ? '24px' : '0px'\"\r\n     [class.active]=\"isActive\"\r\n     [class.disabled]=\"isDisabled\"\r\n     [class.with-hover]=\"withHover\"\r\n     [class.with-divider]=\"withDivider\"\r\n     [matTooltip]=\"tooltipMsg\"\r\n     matTooltipPosition=\"right\"\r\n     (click)=\"onClick($event)\">\r\n  <ng-content></ng-content>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;overflow-x:hidden;overflow-y:auto;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr}.mm-side-bar__title{min-height:174px;padding:44px 0 7px 2px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}\n"] }]
        }], ctorParameters: () => [{ type: SlideOutService }], propDecorators: { tooltipMsg: [{
                type: Input
            }], withTopMargin: [{
                type: Input
            }], withHover: [{
                type: Input
            }], withDivider: [{
                type: Input
            }], isDisabled: [{
                type: Input
            }], soType: [{
                type: Input
            }], clicked: [{
                type: Output
            }] } });

class EmbedComponent extends BaseComponent {
    constructor(embedModeService, sanitizer) {
        super();
        this.embedModeService = embedModeService;
        this.sanitizer = sanitizer;
        /** The url of the application to embed */
        this.url = '';
        /** Use as fullscreen component, or within parent div */
        this.takeOver = false;
    }
    ngOnInit() {
        if (this.url) {
            this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
        }
    }
    ngAfterViewInit() {
        this.embedModeService.embeddedWindow = this.iframeDiv?.nativeElement.contentWindow || null;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbedComponent, deps: [{ token: EmbedModeService }, { token: i2$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EmbedComponent, selector: "spaas-embed", inputs: { url: "url", takeOver: "takeOver" }, viewQueries: [{ propertyName: "iframeDiv", first: true, predicate: ["iframe_div"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (safeUrl) {\r\n  <div [class.fullscreen]=\"takeOver\"\r\n       class=\"embed flex\">\r\n    <iframe #iframe_div [src]=\"safeUrl\"></iframe>\r\n  </div>\r\n}\r\n", styles: [".embed{height:100%;width:100%}.embed.fullscreen{height:100vh;width:100vw;left:0;position:fixed;top:0;z-index:9994}.embed iframe{border:none;height:100%;width:100%}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbedComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-embed', template: "@if (safeUrl) {\r\n  <div [class.fullscreen]=\"takeOver\"\r\n       class=\"embed flex\">\r\n    <iframe #iframe_div [src]=\"safeUrl\"></iframe>\r\n  </div>\r\n}\r\n", styles: [".embed{height:100%;width:100%}.embed.fullscreen{height:100vh;width:100vw;left:0;position:fixed;top:0;z-index:9994}.embed iframe{border:none;height:100%;width:100%}\n"] }]
        }], ctorParameters: () => [{ type: EmbedModeService }, { type: i2$2.DomSanitizer }], propDecorators: { url: [{
                type: Input
            }], takeOver: [{
                type: Input
            }], iframeDiv: [{
                type: ViewChild,
                args: ['iframe_div']
            }] } });

class SyncScrollModel {
    constructor() {
        this.absX = 0;
        this.ratioVisible = 0;
        this.relX = 0;
    }
}

class SyncScrollService {
    constructor() {
        this.scrollX$ = new BehaviorSubject({ absX: 0, relX: 0, ratioVisible: 1 });
    }
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newScrollX(x) {
        // console.log(x);
        this.scrollX$.next(x);
    }
    onNewScrollX() {
        return this.scrollX$.asObservable();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SyncScrollService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SyncScrollService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SyncScrollService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }] });

class SyncScrollDirective {
    constructor(el, syncScrollService) {
        this.el = el;
        this.syncScrollService = syncScrollService;
        this.curSync = new SyncScrollModel();
        this.onDestroy$ = new Subject();
        this.syncScrollService.onNewScrollX()
            .pipe(takeUntil(this.onDestroy$))
            // .pipe(debounceTime(40)) // TODO: evaluate whether to debounce or not
            .subscribe((x) => {
            this.curSync = x;
            this.el.nativeElement.scrollLeft = x.absX;
        });
    }
    onScroll(e) {
        // only broadcast event if different scroll (to prevent slave components from also firing an update)
        if (e.target.scrollLeft !== this.curSync?.absX) {
            this.syncScrollService.newScrollX({
                absX: e.target.scrollLeft,
                relX: e.target.scrollLeft / e.target.scrollWidth,
                ratioVisible: e.target.clientWidth / e.target.scrollWidth,
            });
        }
    }
    ngOnDestroy() {
        this.onDestroy$.next();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SyncScrollDirective, deps: [{ token: i0.ElementRef }, { token: SyncScrollService }], target: i0.ɵɵFactoryTarget.Directive }); }
    static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SyncScrollDirective, selector: "[spaasSyncScroll]", host: { listeners: { "scroll": "onScroll($event)" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SyncScrollDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[spaasSyncScroll]'
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }, { type: SyncScrollService }], propDecorators: { onScroll: [{
                type: HostListener,
                args: ['scroll', ['$event']]
            }] } });

class ResizerComponent {
    constructor(localStorageService, sessionStorageService) {
        this.localStorageService = localStorageService;
        this.sessionStorageService = sessionStorageService;
        this.sizePx = 324;
        this.sizePxChange = new EventEmitter();
        this.minSizePx = 144;
        this.maxSizePx = 9999;
        this.resizeAxis = 'y';
        this.storage = 'local';
        this.storageId = '';
    }
    ngOnInit() {
        if (Number.isNaN(Number(this.sizePx))) {
            throw new Error('the value you provided for sizePx is not a number');
        }
    }
    onDragResizeEnd(e) {
        e.source.reset();
        const inc = this.resizeAxis === 'y' ? e.distance.y : e.distance.x;
        this.sizePx += inc;
        this.sizePx = Math.min(Math.max(this.sizePx, this.minSizePx), this.maxSizePx);
        this.sizePxChange.emit(this.sizePx);
        if (this.storageId) {
            if (this.storage === 'local') {
                this.localStorageService.setItem(this.storageId, this.sizePx);
            }
            else {
                this.sessionStorageService.setItem(this.storageId, this.sizePx);
            }
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizerComponent, deps: [{ token: LocalStorageService }, { token: SessionStorageService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ResizerComponent, selector: "spaas-resizer", inputs: { sizePx: "sizePx", minSizePx: "minSizePx", maxSizePx: "maxSizePx", resizeAxis: "resizeAxis", storage: "storage", storageId: "storageId" }, outputs: { sizePxChange: "sizePxChange" }, ngImport: i0, template: "<div (cdkDragEnded)=\"onDragResizeEnd($event)\"\r\n     [cdkDragLockAxis]=\"resizeAxis\"\r\n     [class.resize-x]=\"resizeAxis === 'x'\"\r\n     cdkDrag\r\n     class=\"resizer\">\r\n</div>\r\n", styles: [".resizer{bottom:0;cursor:ns-resize;height:8px;left:0;position:absolute;transition:background-color .4s;width:100%;z-index:9000}.resizer:before{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);border-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1);border-style:solid;border-width:1px 0 1px 0;content:\"\";height:2px;left:calc(50% - 22px);position:absolute;top:2px;width:44px}.resizer:hover,.resizer.cdk-drag-dragging{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),.2)}.resizer.resize-x{cursor:ew-resize;height:100%;left:auto;right:0;width:8px}.resizer.resize-x:before{border-width:0 1px 0 1px;width:2px;height:44px;left:2px;top:calc(50% - 22px)}\n"], dependencies: [{ kind: "directive", type: i3$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'spaas-resizer', template: "<div (cdkDragEnded)=\"onDragResizeEnd($event)\"\r\n     [cdkDragLockAxis]=\"resizeAxis\"\r\n     [class.resize-x]=\"resizeAxis === 'x'\"\r\n     cdkDrag\r\n     class=\"resizer\">\r\n</div>\r\n", styles: [".resizer{bottom:0;cursor:ns-resize;height:8px;left:0;position:absolute;transition:background-color .4s;width:100%;z-index:9000}.resizer:before{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);border-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1);border-style:solid;border-width:1px 0 1px 0;content:\"\";height:2px;left:calc(50% - 22px);position:absolute;top:2px;width:44px}.resizer:hover,.resizer.cdk-drag-dragging{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),.2)}.resizer.resize-x{cursor:ew-resize;height:100%;left:auto;right:0;width:8px}.resizer.resize-x:before{border-width:0 1px 0 1px;width:2px;height:44px;left:2px;top:calc(50% - 22px)}\n"] }]
        }], ctorParameters: () => [{ type: LocalStorageService }, { type: SessionStorageService }], propDecorators: { sizePx: [{
                type: Input
            }], sizePxChange: [{
                type: Output
            }], minSizePx: [{
                type: Input
            }], maxSizePx: [{
                type: Input
            }], resizeAxis: [{
                type: Input
            }], storage: [{
                type: Input
            }], storageId: [{
                type: Input
            }] } });

/**
 * The SpaasModule offers all building blocks needed for a bespoke SPaaS SPA.
 *
 *  <spaas-okta-intro> to display an intro for okta handling
 *  <spaas-preloader> to add a preloader to your app
 *  OktaAuthGuard to protect your routing
 *  OktaAuthInterceptor to automatically include the token in your http requests
 */
class SpaasModule {
    static forRoot(config) {
        return {
            ngModule: SpaasModule,
            providers: [{ provide: SpaasConfigModel, useValue: config }]
        };
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.12", ngImport: i0, type: SpaasModule, declarations: [BaseComponent,
            BgComponent,
            EmbedComponent,
            IntroComponent,
            MenuComponent,
            MenuSideBarComponent,
            MenuSideBarIconComponent,
            NewVersionComponent,
            PreloaderComponent,
            PwaInstallComponent,
            ResizerComponent,
            SettingsComponent,
            SlideOutComponent,
            SlideOutContentComponent,
            SyncScrollDirective,
            ToggleComponent], imports: [CommonModule,
            FormsModule,
            HttpClientModule,
            MaterialModule,
            ReactiveFormsModule,
            RouterModule, i2$1.ServiceWorkerModule], exports: [BaseComponent,
            BgComponent,
            EmbedComponent,
            IntroComponent,
            MenuComponent,
            MenuSideBarComponent,
            MenuSideBarIconComponent,
            PreloaderComponent,
            ResizerComponent,
            SettingsComponent,
            SlideOutComponent,
            SlideOutContentComponent,
            SyncScrollDirective,
            ToggleComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasModule, providers: [
            {
                provide: APP_INITIALIZER,
                useFactory: (appInitService) => () => {
                    return appInitService.initApp();
                },
                deps: [AppInitService],
                multi: true
            },
            { provide: HTTP_INTERCEPTORS, useClass: OktaAuthInterceptor, multi: true },
        ], imports: [CommonModule,
            FormsModule,
            HttpClientModule,
            MaterialModule,
            ReactiveFormsModule,
            RouterModule,
            ServiceWorkerModule.register('ngsw-worker.js', { enabled: !window.location.host.includes('localhost') })] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SpaasModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [
                        BaseComponent,
                        BgComponent,
                        EmbedComponent,
                        IntroComponent,
                        MenuComponent,
                        MenuSideBarComponent,
                        MenuSideBarIconComponent,
                        NewVersionComponent,
                        PreloaderComponent,
                        PwaInstallComponent,
                        ResizerComponent,
                        SettingsComponent,
                        SlideOutComponent,
                        SlideOutContentComponent,
                        SyncScrollDirective,
                        ToggleComponent,
                    ],
                    exports: [
                        BaseComponent,
                        BgComponent,
                        EmbedComponent,
                        IntroComponent,
                        MenuComponent,
                        MenuSideBarComponent,
                        MenuSideBarIconComponent,
                        PreloaderComponent,
                        ResizerComponent,
                        SettingsComponent,
                        SlideOutComponent,
                        SlideOutContentComponent,
                        SyncScrollDirective,
                        ToggleComponent,
                    ],
                    imports: [
                        CommonModule,
                        FormsModule,
                        HttpClientModule,
                        MaterialModule,
                        ReactiveFormsModule,
                        RouterModule,
                        ServiceWorkerModule.register('ngsw-worker.js', { enabled: !window.location.host.includes('localhost') }),
                    ],
                    providers: [
                        {
                            provide: APP_INITIALIZER,
                            useFactory: (appInitService) => () => {
                                return appInitService.initApp();
                            },
                            deps: [AppInitService],
                            multi: true
                        },
                        { provide: HTTP_INTERCEPTORS, useClass: OktaAuthInterceptor, multi: true },
                    ]
                }]
        }] });

class EmbeddedOnlyGuard {
    constructor(embedModeService, router) {
        this.embedModeService = embedModeService;
        this.router = router;
    }
    isIframe() {
        const isIframe = this.embedModeService.getEmbedMode().isIframe();
        if (!isIframe) {
            // set default url to "home". If "home" does not exist, router will fall back to redirect config
            return this.router.parseUrl('/home');
        }
        return isIframe;
    }
    // CAN LOAD: FOR FEATURE MODULES SECURITY
    canLoad(route) {
        return this.isIframe();
    }
    // CAN ACTIVATE: FOR ROUTES SECURITY
    canActivate(route, state) {
        return this.isIframe();
    }
    canActivateChild(route, state) {
        return this.canActivate(route, state);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbeddedOnlyGuard, deps: [{ token: EmbedModeService }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbeddedOnlyGuard, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmbeddedOnlyGuard, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: EmbedModeService }, { type: i3.Router }] });

class OktaAuthGuard {
    constructor(activeRouteService, oktaService) {
        this.activeRouteService = activeRouteService;
        this.oktaService = oktaService;
    }
    // CAN LOAD: FOR FEATURE MODULES SECURITY
    canLoad(route) {
        return !!this.oktaService.getCachedAccessToken();
    }
    // CAN ACTIVATE: FOR ROUTES SECURITY
    canActivate(route, state) {
        this.activeRouteService.newActiveRoute(state.url, route.queryParams, route.params);
        return !!this.oktaService.getCachedAccessToken();
    }
    canActivateChild(route, state) {
        return this.canActivate(route, state);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaAuthGuard, deps: [{ token: ActiveRouteService }, { token: OktaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaAuthGuard, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OktaAuthGuard, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: ActiveRouteService }, { type: OktaService }] });

/**
 * Enum used as msgType in the PostMessageModel. Will be used to know how to respond to a certain message.
 */
var PostMessageEnum;
(function (PostMessageEnum) {
    PostMessageEnum["getTheme"] = "1_getTheme";
    PostMessageEnum["setTheme"] = "2_setTheme";
})(PostMessageEnum || (PostMessageEnum = {}));
/**
 * Model used to post messages from and to an iframe child app.
 *
 * @property {PostMessageEnum} msgType the type defined by PostMessageEnum. Will be used to know how
 * to respond to a certain message
 * @property {any} msgData any data you want to include in the PostMessage
 */
class PostMessageModel {
    constructor(type, data = '') {
        this.msgType = type;
        this.msgData = data;
    }
}

const REGEX_DEC = '^-?(0|[1-9]\\d*)(\\.\\d+)?$';
const REGEX_DEC_OR_HASH = '^[#]{1}$|^-?(0|[1-9]\\d*)(\\.\\d+)?$';
const REGEX_INT = '^[-]?\\d*$'; // only integers, also negative
const REGEX_INT_OR_1DEC = '^-?\\d+([.]\\d)?$';
const REGEX_POSITIVE_INT = '^\\d+$';

class PostMessageService {
    constructor(embedModeService, settingsService, themeService) {
        this.embedModeService = embedModeService;
        this.settingsService = settingsService;
        this.themeService = themeService;
        this.onEmbedMode();
        this.startListening();
    }
    onEmbedMode() {
        this.embedModeService.onNewEmbedMode()
            .subscribe((mode) => {
            if (mode?.isIframe()) {
                // ask for theme from parent
                this.postMessage(window.parent, new PostMessageModel(PostMessageEnum.getTheme));
            }
        });
    }
    startListening() {
        this.listenToPostMessages()
            .subscribe((msg) => {
            // **************************************
            // MESSAGES TO BE PROCESSED BY PARENT
            // request for theme
            if (msg.msgType === PostMessageEnum.getTheme) {
                console.log('parent received request for theme');
                this.postMessage(this.embedModeService.embeddedWindow, new PostMessageModel(PostMessageEnum.setTheme, this.themeService.getActiveTheme().name));
            }
            // **************************************
            // MESSAGES TO BE PROCESSED BY CHILD
            // set theme received from parent
            if (msg.msgType === PostMessageEnum.setTheme) {
                console.log('child received theme from parent: ' + msg.msgData);
                const settings = this.settingsService.getSettings();
                settings.dark = msg.msgData === 'dark';
                this.settingsService.newSettings(settings);
                this.themeService.setActiveTheme(msg.msgData);
            }
        });
    }
    /**
     * When you've embedded a SPaaS app using an iframe, you can use this method to listen to
     * the messages it will post. Some messages are automatically processed, check the doc.
     */
    listenToPostMessages() {
        return fromEvent(window, 'message')
            .pipe(map((m) => new PostMessageModel(m?.data?.msgType || '', m?.data?.msgData || '')));
    }
    /**
     * When you've embedded a SPaaS app in an iframe and want to reply to some messages it will post,
     * you can use this method to do so.
     *
     * @param source the MessageEventSource of the iframe. You can retrieve its source by using
     * '@ViewChild('your_iframe_div') iframeDiv: ElementRef;' and then get 'this.iframeDiv.nativeElement.contentWindow'
     * @param msg the actual message to send to the child app in the iframe
     */
    postMessage(source, msg) {
        if (source) {
            source.postMessage(msg, { targetOrigin: '*' });
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PostMessageService, deps: [{ token: EmbedModeService }, { token: SettingsService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PostMessageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PostMessageService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: EmbedModeService }, { type: SettingsService }, { type: ThemeService }] });

class SnackbarService {
    static getConfirmId(type) {
        return type + '_' + performance.now();
    }
    constructor(snackbar, zone) {
        this.snackbar = snackbar;
        this.zone = zone;
        this.DEF_DURATION = 6000;
        this.duration = this.DEF_DURATION;
        this.confirm$ = new BehaviorSubject('');
        this.sbConfig = new MatSnackBarConfig();
    }
    /**
     * Shows a Material snackbar.
     *
     * @param message the message to show in the snackbar
     * @param action (optional) the message to show in the snackbar action button. When no action is provided, the button
     * will not show
     * @param append (optional, default true) specifies whether to append the new snackbar message to the previous one
     * if a previous snackbar is still active
     * @param duration (optional) set a one-time specific duration in milliseconds, just for this snackbar instance
     */
    message(message, action = '', append = true, duration = this.duration) {
        this.open(message, action, append, duration, false);
    }
    /**
     * Shows a Material snackbar as an error (red background).
     *
     * @param message the message to show in the snackbar
     * @param action (optional) the message to show in the snackbar action button. When no action is provided, the button
     * will not show
     * @param append (optional, default true) specifies whether to append the new snackbar message to the previous one
     * if a previous snackbar is still active
     * @param duration (optional) set a one-time specific duration in milliseconds, just for this snackbar instance
     */
    error(message, action = '', append = true, duration = this.duration) {
        this.open(message, action, append, duration, true);
    }
    open(message, action, append, duration, isError) {
        this.zone.run(() => {
            if (append && this.snackbar._openedSnackBarRef?.instance?.data?.message) {
                message = this.snackbar._openedSnackBarRef.instance.data.message + '\n------\n' + message;
            }
            // reset panelClass in case the previous snackbar was an error
            this.sbConfig.panelClass = isError ? 'bg-error' : '';
            this.sbConfig.duration = duration;
            this.snackbar.open(message, action, this.sbConfig);
        });
    }
    /**
     * Shows a Material snackbar which awaits confirmation.
     *
     * @param message the message to show in the snackbar
     * @param action the message to show in the snackbar action button. When no action is provided, the button
     * will show "Got it"
     * @param confirmId a unique identifier by which you can recognise the confirmation response
     * that you get when listening to "onNewConfirm". Use static method "SnackbarService.getConfirmId" to get a unique id.
     * @param duration (optional) set a one-time specific duration in milliseconds, just for this snackbar instance
     */
    confirm(message, action = 'Got it', confirmId, duration = this.duration) {
        this.zone.run(() => {
            // reset panelClass in case the previous snackbar was an error
            this.sbConfig.panelClass = '';
            this.sbConfig.duration = duration;
            const snack = this.snackbar.open(message, action, this.sbConfig);
            snack.onAction()
                .subscribe(() => {
                this.newConfirm(confirmId);
            });
        });
    }
    /**
     * Set the global duration for all snackbars
     *
     * @param ms duration in milliseconds
     */
    setDuration(ms) {
        this.duration = ms;
    }
    /**
     * Reset the global duration for all snackbars to default (6000)
     */
    resetDuration() {
        this.duration = this.DEF_DURATION;
    }
    // ********************************************************************************************************
    // BROADCAST DATA
    // ********************************************************************************************************
    newConfirm(newConfirm) {
        this.confirm$.next(newConfirm);
    }
    onNewConfirm() {
        return this.confirm$.asObservable();
    }
    close() {
        this.zone.run(() => {
            this.snackbar.dismiss();
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarService, deps: [{ token: i1$1.MatSnackBar }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SnackbarService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: i1$1.MatSnackBar }, { type: i0.NgZone }] });

// MODULE

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

export { ActiveRouteService, BaseComponent, BgComponent, ConfigService, DATA__HAS_MENU, DATA__THEME_DARK, DATA__THEME_LIGHT, EmbedComponent, EmbeddedOnlyGuard, IntroComponent, LocalStorageService, MenuComponent, MenuSideBarComponent, MenuSideBarIconComponent, NewVersionConfigModel, NewVersionService, OktaAuthGuard, OktaConfigModel, OktaService, OktaUserModel, PostMessageEnum, PostMessageModel, PostMessageService, PreloaderComponent, PreloaderService, REGEX_DEC, REGEX_DEC_OR_HASH, REGEX_INT, REGEX_INT_OR_1DEC, REGEX_POSITIVE_INT, ResizerComponent, SessionStorageService, SettingsComponent, SettingsModel, SettingsService, SlideOutComponent, SlideOutContentComponent, SlideOutService, SnackbarService, SpaasConfigModel, SpaasExtConfigModel, SpaasModule, SyncScrollDirective, SyncScrollService, ThemeModel, ThemeService, ToggleComponent, UtilsService, dark, light };
//# sourceMappingURL=ngx-gem-spaas.mjs.map