@rosen-group/ngx-onboarding
Version:
Onboarding module for Angular applications
1,113 lines • 61.6 kB
JavaScript
import { timer, interval, of } from 'rxjs';
import * as i0 from '@angular/core';
import { Injectable, Inject, EventEmitter, Pipe, Component, ViewEncapsulation, Input, ViewChild, NgModule } from '@angular/core';
import * as i3 from '@angular/common';
import { DOCUMENT, CommonModule } from '@angular/common';
import * as i3$1 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i4 from '@angular/material/badge';
import { MatBadgeModule } from '@angular/material/badge';
import * as i5 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i6 from '@angular/material/menu';
import { MatMenuModule } from '@angular/material/menu';
import * as i2 from '@angular/platform-browser';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
/**
* Wrapper for native implementations of querySelector from window.document
*/
class BrowserDOMSelectorService {
constructor(doc) {
this.doc = doc;
}
/** see https://developer.mozilla.org/de/docs/Web/API/Document/querySelectorAll */
querySelectorAll(cssQuery) {
return this.doc.querySelectorAll(cssQuery);
}
/** see https://developer.mozilla.org/de/docs/Web/API/Document/querySelector */
querySelector(cssQuery) {
return this.doc.querySelector(cssQuery);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BrowserDOMSelectorService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BrowserDOMSelectorService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BrowserDOMSelectorService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }] });
/**
* Container to pass visible onboarding elements from onboarding service
* to onboarding component (which can be grouped by their "group" field).
*
* Current group of elements can be accessed via currentItems(). Next group can be accessed via nextItems().
*
* Container does not have immediate access to grouping keys since elements are stored in jagged array.
*/
class OnboardingItemContainer {
constructor() {
this.items = [];
this.totalCount = 0;
this.currentGroupIndex = 0;
}
get isEmpty() {
return !this.items || this.totalCount === 0;
}
/**
* Check if there is another group of visible onboarding items
*/
get hasNext() {
return this.items && this.currentGroupIndex < (this.items.length - 1);
}
/**
* Return current group of visible onboarding items
*/
get currentItem() {
if (this.items && this.currentGroupIndex < this.items.length) {
return this.items[this.currentGroupIndex];
}
return null;
}
/**
* Return list of All visible onboarding items (regardless of grouping)
*/
get allItems() {
return this.items.slice();
}
/**
* Return count of all items (regardless of grouping)
*/
get totalLength() {
return this.totalCount;
}
/**
* Return next group of visible onboarding items
*/
nextItem() {
if (this.hasNext) {
this.currentGroupIndex++;
return this.currentItem;
}
return null;
}
/**
* Add new group of items
*/
add(items) {
if (items) {
this.items.push(...items);
this.totalCount += items.length;
}
}
/**
* Clear items from container
*/
clear() {
this.items = [];
this.totalCount = 0;
this.currentGroupIndex = 0;
}
}
/**
* contains static helper methods for [[HTMLELement]]
*/
class OnboardingHtmlElementHelper {
static isVisible(htmlElement) {
if (!htmlElement || typeof getComputedStyle !== 'function') {
return false;
}
const style = getComputedStyle(htmlElement);
if (!htmlElement.offsetParent && style.position !== 'fixed') {
return false;
}
return !(style.opacity === '0' || style.display === 'none' || style.visibility === 'hidden' || style.visibility === 'collapse');
}
/**
* true if element is visible in view (not scrolled out) or false if not
*/
static isNotScrolledOut(htmlElement) {
if (!htmlElement || !htmlElement.offsetParent) {
return false;
}
const parent = htmlElement.offsetParent;
const parentTop = parent.scrollTop;
const parentBottom = parentTop + parent.offsetHeight;
const elementTop = htmlElement.offsetTop;
const elementBottom = elementTop + htmlElement.offsetHeight;
return parentTop < elementTop && parentBottom > elementBottom;
}
/**
* true if element and all parents are visible in view (not scrolled out) or false if not
*/
static isVisibleInViewWithParents(htmlElement) {
do {
if (htmlElement && htmlElement.tagName && htmlElement.tagName.toLowerCase() === 'body') {
return true;
}
if (!OnboardingHtmlElementHelper.isVisible(htmlElement)) {
return false;
}
if (htmlElement.scrollTop > 0) {
if (!OnboardingHtmlElementHelper.isNotScrolledOut(htmlElement)) {
return false;
}
}
} while (htmlElement = htmlElement.offsetParent);
return true;
}
/**
* returns the position of element in document
*/
static getPosition(htmlElement) {
const rect = htmlElement.getBoundingClientRect();
if (typeof DOMRect !== 'undefined' && rect instanceof DOMRect) {
return {
fixed: OnboardingHtmlElementHelper.isFixed(htmlElement),
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height
};
}
return {
fixed: OnboardingHtmlElementHelper.isFixed(htmlElement),
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height
};
}
static isFixed(htmlElement) {
if (!htmlElement || typeof getComputedStyle !== 'function') {
return false;
}
const style = getComputedStyle(htmlElement);
if (style.position === 'fixed') {
return true;
}
return OnboardingHtmlElementHelper.isFixed(htmlElement.offsetParent);
}
}
/**
* Base class for storing the onboarding item enabled status. Can be overridden with own implementations
* if you don't want to store the settings in the local storage
*/
class EnabledStatusBaseService {
}
var OnboardingButtonsPosition;
(function (OnboardingButtonsPosition) {
OnboardingButtonsPosition[OnboardingButtonsPosition["BottomRight"] = 0] = "BottomRight";
OnboardingButtonsPosition[OnboardingButtonsPosition["Bottom"] = 1] = "Bottom";
OnboardingButtonsPosition[OnboardingButtonsPosition["BottomLeft"] = 2] = "BottomLeft";
OnboardingButtonsPosition[OnboardingButtonsPosition["Left"] = 3] = "Left";
OnboardingButtonsPosition[OnboardingButtonsPosition["TopLeft"] = 4] = "TopLeft";
OnboardingButtonsPosition[OnboardingButtonsPosition["Top"] = 5] = "Top";
OnboardingButtonsPosition[OnboardingButtonsPosition["TopRight"] = 6] = "TopRight";
OnboardingButtonsPosition[OnboardingButtonsPosition["Right"] = 7] = "Right";
})(OnboardingButtonsPosition || (OnboardingButtonsPosition = {}));
/**
* Base class for storing the onboarding item seen status. Can be overridden with own implementations
* if you don't want to store the settings in the local storage
*/
class SeenSelectorsBaseService {
}
const addSeenSelectorDebounceTime = 1000;
const enabledChangedDebounceTime = 1000;
const refreshTime = 2000;
/**
* The OnboardingService manages the configuration and the status of the onboarding component.
*
* The OnboardingComponent listens to the visibleItemsChanged event and retrieves new onboarding items from the visibleItems object.
*/
class OnboardingService {
constructor(browserDomSelectorService, loadAndSaveSeenSelectorsService, loadAndSaveEnabledStatusService, errorHandler, zone) {
this.browserDomSelectorService = browserDomSelectorService;
this.loadAndSaveSeenSelectorsService = loadAndSaveSeenSelectorsService;
this.loadAndSaveEnabledStatusService = loadAndSaveEnabledStatusService;
this.errorHandler = errorHandler;
this.zone = zone;
/**
* Container with currently visible onboarding items (grouped).
* OnboardingComponent must iterate through these groups.
*
* called by OnboardingComponent
*/
this.visibleItems = new OnboardingItemContainer();
/**
* called by OnboardingComponent
*/
this.visibleItemsChanged = new EventEmitter();
this.defaultConfiguration = {
iconConfiguration: {
matIconName: 'contact_support',
matBadgeColor: 'accent',
matBadgePosition: 'below after',
matBadgeSize: 'medium'
},
textConfiguration: {
regularFontFamily: 'Roboto, "Segoe UI", Helvetica, Arial, sans-serif;',
scriptFontFamily: '"Gochi Hand", Georgia, "Segoe Script", "Comic Sans MS", serif'
},
buttonsConfiguration: {
position: OnboardingButtonsPosition.BottomRight,
horizontalDistanceToBorderInPx: 50,
verticalDistanceToBorderInPx: 40
}
};
this.configuration = this.defaultConfiguration;
/* this is the default setting. can be changed by configure()*/
this.init();
}
/**
* returns the count of the registered items
*/
get registeredItemsCount() {
return this.items.length;
}
/**
* Configures the onboarding icons and fonts.
*
* If you want to change the default settings, then call this in your module where you import this
* service as provider and set global defaults like icon properties
*/
configure(configuration) {
if (typeof configuration === 'undefined') {
throw new Error('Configuration must not be undefined or null');
}
// new merge default configuration with user configuration
const mergedConfig = {
iconConfiguration: Object.assign({}, this.defaultConfiguration.iconConfiguration),
textConfiguration: Object.assign({}, this.defaultConfiguration.textConfiguration),
buttonsConfiguration: Object.assign({}, this.defaultConfiguration.buttonsConfiguration)
};
if (configuration.iconConfiguration) {
Object.assign(mergedConfig.iconConfiguration, configuration.iconConfiguration);
// icon shape configurations are mutually exclusive so a special checks are needed for that
if (!configuration.iconConfiguration.matIconName &&
(configuration.iconConfiguration.fontSet || configuration.iconConfiguration.svgIcon)) {
mergedConfig.iconConfiguration.matIconName = undefined; // if the user wants fontSet than we have to disable matIconName
}
}
if (configuration.textConfiguration) {
Object.assign(mergedConfig.textConfiguration, configuration.textConfiguration);
}
if (configuration.buttonsConfiguration) {
Object.assign(mergedConfig.buttonsConfiguration, configuration.buttonsConfiguration);
}
this.configuration = mergedConfig;
}
/** used internal only to retrieve to configuration from configure()*/
getConfiguration() {
return this.configuration;
}
/**
* registers [[OnboardingItem]]s in items, returns the method to unregister items (e.g. in ngOnDestroy)
*/
register(items) {
this.items.push(...items);
return () => {
// this.items = filter(this.items, thisItem => !some(items, item => thisItem.selector === item.selector));
this.items = this.items.filter(thisItem => !items.some(item => thisItem.selector === item.selector));
};
}
/**
* Check which onboarding items are visible. Emit visibleItemsChanged event.
* called by OnboardingComponent
*/
check() {
try {
if (this.isEnabled() && this.visibleItems && this.visibleItems.totalLength > 0) {
return;
}
const matches = [];
const notSeenItems = this.getNotSeenItems();
if (notSeenItems) {
notSeenItems.forEach(item => {
const elements = Array.from(this.browserDomSelectorService.querySelectorAll(item.selector));
if (elements && elements.length > 0) {
let element = elements.find((e) => OnboardingHtmlElementHelper.isVisibleInViewWithParents(e));
if (element) {
if (item.toParent && element.offsetParent) {
element = element.offsetParent;
}
if (element) {
matches.push({
item: item,
element: element
});
}
}
}
});
}
this.visibleItems.clear();
this.visibleItems.add(matches);
this.visibleItemsChanged.emit();
}
catch (error) {
this.errorHandler.handleError(error);
}
}
/**
* Mark all visible items as SEEN, remove them from visible list and emit change event.
* called by OnboardingComponent
*/
hide() {
this.visibleItems.allItems.forEach(i => {
this.addToSeenSelectors(i.item.selector);
});
this.visibleItems.clear();
this.visibleItemsChanged.emit();
}
/**
* called by OnboardingComponent
*
* Disables the onboarding
*/
disable() {
this.hide();
this.enabled = false;
this.visibleItemsChanged.emit();
this.enabledChanged();
}
/**
* called by OnboardingComponent
*
* Enables the onboarding
*/
enable() {
this.enabled = true;
this.visibleItems.clear();
this.check();
this.enabledChanged();
}
/**
* called by OnboardingComponent
*/
isEnabled() {
return this.enabled;
}
/**
* called by OnboardingComponent
*/
clearSeenSelectors() {
this.seenSelectors = [];
this.seenSelectorsChanged();
}
init() {
this.items = [];
this.seenSelectors = [];
this.visibleItems.clear();
this.loadSeenSelectors();
this.loadEnabledStatus();
this.startRefreshTimer();
}
addToSeenSelectors(selector) {
this.seenSelectors.push(selector);
this.seenSelectorsChanged();
}
seenSelectorsChanged() {
if (this.addSeenSelectorDebounceSubscription) {
this.addSeenSelectorDebounceSubscription.unsubscribe();
}
const source = timer(addSeenSelectorDebounceTime);
this.addSeenSelectorDebounceSubscription = source.subscribe(() => {
this.saveSeenSelectors();
});
}
enabledChanged() {
if (this.enabledChangedDebounceSubscription) {
this.enabledChangedDebounceSubscription.unsubscribe();
}
const source = timer(enabledChangedDebounceTime);
this.enabledChangedDebounceSubscription = source.subscribe(() => {
this.saveEnabledStatus();
});
}
getNotSeenItems() {
return this.items.filter(i => !this.seenSelectors.some(seen => seen === i.selector));
}
startRefreshTimer() {
if (this.refreshSubscription) {
this.refreshSubscription.unsubscribe();
}
const source = interval(refreshTime);
this.zone.runOutsideAngular(() => {
this.refreshSubscription = source.subscribe(() => {
this.zone.run(() => {
this.check();
});
});
});
}
loadSeenSelectors() {
this.loadAndSaveSeenSelectorsService.load().subscribe(seenSelectors => {
this.seenSelectors = seenSelectors;
});
}
saveSeenSelectors() {
this.loadAndSaveSeenSelectorsService.save(this.seenSelectors);
}
loadEnabledStatus() {
this.loadAndSaveEnabledStatusService.load().subscribe(enabled => {
this.enabled = enabled;
});
}
saveEnabledStatus() {
this.loadAndSaveEnabledStatusService.save(this.enabled);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingService, deps: [{ token: BrowserDOMSelectorService }, { token: SeenSelectorsBaseService }, { token: EnabledStatusBaseService }, { token: i0.ErrorHandler }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingService, providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */
}]
}], ctorParameters: () => [{ type: BrowserDOMSelectorService }, { type: SeenSelectorsBaseService }, { type: EnabledStatusBaseService }, { type: i0.ErrorHandler }, { type: i0.NgZone }] });
/**
* Base interface for translatorservice (used for core ngx-onboarding labels)
*/
class TranslatorBaseService {
}
/**
* Pipe for internal usage to translate the text on the onboarding component like disable, enable
*/
class PrimitiveTranslatePipe {
constructor(translateService) {
this.translateService = translateService;
}
transform(query, ...args) {
return this.translateService.instant(query);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PrimitiveTranslatePipe, deps: [{ token: TranslatorBaseService }], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: PrimitiveTranslatePipe, isStandalone: false, name: "translate" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: PrimitiveTranslatePipe, decorators: [{
type: Pipe,
args: [{
name: 'translate',
pure: true,
standalone: false
}]
}], ctorParameters: () => [{ type: TranslatorBaseService }] });
/**
* onboarding button including context menu (see header.component in rolib/navigation)
*/
class OnboardingButtonComponent {
constructor(onboardingService) {
this.onboardingService = onboardingService;
const config = onboardingService.getConfiguration();
if (config) {
this.iconConfig = config.iconConfiguration;
}
}
/**
* if true, the count is visible
* is true, if the onboarding service is disabled and at least one onboarding item is visible
*/
get showOnboardingItemCount() {
return !this.onboardingService.isEnabled() &&
this.onboardingService.visibleItems &&
this.onboardingService.visibleItems.totalLength > 0;
}
/**
* gets the visible item count
*/
get onboardingItemCount() {
return this.onboardingService.visibleItems.totalLength;
}
/**
* used by template
* enables the onboarding service
*/
enableOnboarding() {
this.onboardingService.enable();
}
/**
* disables the onboarding service
*/
disableOnboarding() {
this.onboardingService.disable();
}
/**
* resets the onboarding service
* removes all selectors from seen selectors
*/
clearOnboarding() {
this.onboardingService.clearSeenSelectors();
}
/**
* is true, if the onboarding service is enabled
*/
isOnboardingEnabled() {
return this.onboardingService.isEnabled();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingButtonComponent, deps: [{ token: OnboardingService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: OnboardingButtonComponent, isStandalone: false, selector: "rosen-onboarding-button", ngImport: i0, template: "<div class=\"onboarding-button-container\">\n <mat-menu #onboardingMenu=\"matMenu\">\n <button mat-menu-item (click)=\"enableOnboarding()\" *ngIf=\"!isOnboardingEnabled()\"\n class=\"onboarding-menu-button\">\n <mat-icon>add_alert</mat-icon>\n {{'ONBOARDING_ENABLE'|translate}}\n </button>\n <button mat-menu-item (click)=\"disableOnboarding()\" *ngIf=\"isOnboardingEnabled()\"\n class=\"onboarding-menu-button\">\n <mat-icon>notifications_off</mat-icon>\n {{'ONBOARDING_DISABLE'|translate}}\n </button>\n <button mat-menu-item (click)=\"clearOnboarding()\" class=\"onboarding-menu-button\">\n <mat-icon>undo</mat-icon>\n {{'ONBOARDING_CLEAR'|translate}}\n </button>\n </mat-menu>\n <button *ngIf=\"iconConfig\" mat-icon-button [matMenuTriggerFor]=\"onboardingMenu\" class=\"onboarding-button\" [title]=\"'ONBOARDING'|translate\">\n <mat-icon *ngIf=\"iconConfig.matIconName && !iconConfig.svgIcon && !iconConfig.fontSet\"\n [matBadgeColor]=\"iconConfig.matBadgeColor\" [matBadgeHidden]=\"isOnboardingEnabled()\" [matBadge]=\"onboardingItemCount\"\n [matBadgePosition]=\"iconConfig.matBadgePosition\" [matBadgeSize]=\"iconConfig.matBadgeSize\"\n [matBadgeOverlap]=\"true\">{{iconConfig.matIconName}}\n </mat-icon>\n <mat-icon *ngIf=\"iconConfig.svgIcon || iconConfig.fontSet\"\n [svgIcon]=\"iconConfig.svgIcon\"\n [fontSet]=\"iconConfig.fontSet\" [fontIcon]=\"iconConfig.fontIcon\"\n [matBadgeColor]=\"iconConfig.matBadgeColor\" [matBadgeHidden]=\"isOnboardingEnabled()\" [matBadge]=\"onboardingItemCount\"\n [matBadgePosition]=\"iconConfig.matBadgePosition\" [matBadgeSize]=\"iconConfig.matBadgeSize\"\n [matBadgeOverlap]=\"true\">\n </mat-icon>\n </button>\n</div>\n", styles: [".onboarding-button-container{position:relative;text-align:center}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i4.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "pipe", type: PrimitiveTranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingButtonComponent, decorators: [{
type: Component,
args: [{ selector: 'rosen-onboarding-button', encapsulation: ViewEncapsulation.None, standalone: false, template: "<div class=\"onboarding-button-container\">\n <mat-menu #onboardingMenu=\"matMenu\">\n <button mat-menu-item (click)=\"enableOnboarding()\" *ngIf=\"!isOnboardingEnabled()\"\n class=\"onboarding-menu-button\">\n <mat-icon>add_alert</mat-icon>\n {{'ONBOARDING_ENABLE'|translate}}\n </button>\n <button mat-menu-item (click)=\"disableOnboarding()\" *ngIf=\"isOnboardingEnabled()\"\n class=\"onboarding-menu-button\">\n <mat-icon>notifications_off</mat-icon>\n {{'ONBOARDING_DISABLE'|translate}}\n </button>\n <button mat-menu-item (click)=\"clearOnboarding()\" class=\"onboarding-menu-button\">\n <mat-icon>undo</mat-icon>\n {{'ONBOARDING_CLEAR'|translate}}\n </button>\n </mat-menu>\n <button *ngIf=\"iconConfig\" mat-icon-button [matMenuTriggerFor]=\"onboardingMenu\" class=\"onboarding-button\" [title]=\"'ONBOARDING'|translate\">\n <mat-icon *ngIf=\"iconConfig.matIconName && !iconConfig.svgIcon && !iconConfig.fontSet\"\n [matBadgeColor]=\"iconConfig.matBadgeColor\" [matBadgeHidden]=\"isOnboardingEnabled()\" [matBadge]=\"onboardingItemCount\"\n [matBadgePosition]=\"iconConfig.matBadgePosition\" [matBadgeSize]=\"iconConfig.matBadgeSize\"\n [matBadgeOverlap]=\"true\">{{iconConfig.matIconName}}\n </mat-icon>\n <mat-icon *ngIf=\"iconConfig.svgIcon || iconConfig.fontSet\"\n [svgIcon]=\"iconConfig.svgIcon\"\n [fontSet]=\"iconConfig.fontSet\" [fontIcon]=\"iconConfig.fontIcon\"\n [matBadgeColor]=\"iconConfig.matBadgeColor\" [matBadgeHidden]=\"isOnboardingEnabled()\" [matBadge]=\"onboardingItemCount\"\n [matBadgePosition]=\"iconConfig.matBadgePosition\" [matBadgeSize]=\"iconConfig.matBadgeSize\"\n [matBadgeOverlap]=\"true\">\n </mat-icon>\n </button>\n</div>\n", styles: [".onboarding-button-container{position:relative;text-align:center}\n"] }]
}], ctorParameters: () => [{ type: OnboardingService }] });
class OnboardingItem {
constructor() {
this.disableSpotlight = false;
this.disableBackground = false;
this.transparentSpotlight = false;
this.toParent = false;
}
}
class VisibleOnboardingItem {
constructor(item, element) {
this.item = item;
this.element = element;
}
}
/**
* return the global native browser window object
*/
function _window() {
return window;
}
/**
* Abstraction of the window reference
*/
class WindowRef {
get nativeWindow() {
return _window();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: WindowRef, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: WindowRef, providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: WindowRef, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }]
}] });
const topPadding = 25;
const rightPadding = 25;
const leftPadding = 25;
/**
* used by onboarding component
* shows the headline and detail text of the OnboardingItem
* calculates the positions of the item
*/
class OnboardingItemComponent {
constructor(translatorService, windowRef) {
this.translatorService = translatorService;
this.windowRef = windowRef;
}
/**
* calculates the position of the OnboardingItemComponent
*/
getStyle() {
const pos = OnboardingHtmlElementHelper.getPosition(this.item.element);
let transform = 'none';
switch (this.item.item.position) {
case 'top':
pos.x += this.item.element.offsetWidth / 2;
if (pos.x < this.getContainerWidth() / 2) {
pos.x = this.getContainerWidth() / 2;
}
else if (pos.x > this.getWindowScreenWidth() - this.getContainerWidth()) {
pos.x = this.getWindowScreenWidth() - this.getContainerWidth();
}
pos.y -= topPadding;
transform = 'translate(-50%,-100%)';
break;
case 'right':
pos.x += Math.min(this.item.element.offsetWidth + rightPadding, this.getWindowScreenWidth() - this.getContainerWidth() / 2);
pos.y += this.item.element.offsetHeight / 2;
if (pos.y < 0) {
pos.y = 0;
}
else if (pos.y > this.getWindowScreenHeight() - this.getContainerHeight() / 2) {
pos.y = this.getWindowScreenHeight() - this.getContainerHeight() / 2;
}
transform = 'translateY(-50%)';
break;
case 'left':
pos.x -= leftPadding;
pos.y += this.item.element.offsetHeight / 2;
if (pos.y < 0) {
pos.y = 0;
}
else if (pos.y > this.getWindowScreenHeight() - this.getContainerHeight() / 2) {
pos.y = this.getWindowScreenHeight() - this.getContainerHeight() / 2;
}
transform = 'translate(-100%,-50%)';
break;
case 'topleft':
pos.x -= leftPadding;
pos.y -= topPadding;
if (pos.y < 0) {
pos.y = 0;
}
else if (pos.y > this.getWindowScreenHeight() - this.getContainerHeight() / 2) {
pos.y = this.getWindowScreenHeight() - this.getContainerHeight() / 2;
}
transform = 'translate(-100%,-100%)';
break;
case 'bottom':
default:
pos.x += this.item.element.offsetWidth / 2;
if (pos.x < this.getContainerWidth() / 2) {
pos.x = this.getContainerWidth() / 2;
}
else if (pos.x > this.getWindowScreenWidth() - this.getContainerWidth()) {
pos.x = this.getWindowScreenWidth() - this.getContainerWidth();
}
pos.y += this.item.element.offsetHeight;
transform = 'translate(-50%,25%)';
break;
}
return {
left: pos.x + 'px',
transform: transform,
top: pos.y + 'px'
};
}
getHeadline() {
const description = this.item.item.descriptions?.find(d => d.language === this.translatorService.currentLang);
return description ? description.headline : this.item.item.headline;
}
getDetails() {
const description = this.item.item.descriptions?.find(d => d.language === this.translatorService.currentLang);
return description ? description.details : this.item.item.details;
}
getTextAlignClass() {
if ((this.item.item.textAlign == null) || this.item.item.textAlign === 'center') {
return ''; // ==> center
}
return `align-${this.item.item.textAlign}`;
}
getContainerWidth() {
return this.container.nativeElement.offsetWidth;
}
getContainerHeight() {
return this.container.nativeElement.offsetHeight;
}
getWindowScreenWidth() {
return this.windowRef.nativeWindow ? this.windowRef.nativeWindow.screen.width : 1024;
}
getWindowScreenHeight() {
return this.windowRef.nativeWindow ? this.windowRef.nativeWindow.screen.height : 768;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingItemComponent, deps: [{ token: TranslatorBaseService }, { token: WindowRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: OnboardingItemComponent, isStandalone: false, selector: "rosen-onboarding-item", inputs: { item: "item" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, static: true }], ngImport: i0, template: "<div #container class=\"onboarding-item\" [ngStyle]=\"getStyle()\">\n <div class=\"onboarding-item-header text-color animated script-font fade-in-left\" ngClass=\"getTextAlignClass()\">\n {{getHeadline()}}\n </div>\n <div class=\"onboarding-item-details text-color animated regular-font fade-in-right\" ngClass=\"getTextAlignClass()\">\n {{getDetails()}}\n </div>\n</div>\n", styles: [".onboarding-item{position:absolute}.onboarding-item .text-color{color:#fff}.onboarding-item .onboarding-item-header{font-size:24px;text-align:center}.onboarding-item .onboarding-item-details{font-size:14px;text-align:center}.onboarding-item .align-left{text-align:left}.onboarding-item .align-right{text-align:right}.onboarding-item .animated{animation-duration:1s}.onboarding-item .fade-in-right{animation-name:fadeInRight}.onboarding-item .fade-in-left{animation-name:fadeInLeft}.onboarding-item .fade-in-top{animation-name:fadeInTop}.onboarding-item .fade-in-bottom{animation-name:fadeInBottoim}@keyframes fadeInRight{0%{opacity:0;transform:translate(-20px)}to{opacity:1;transform:translate(0)}}@keyframes fadeInLeft{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}@keyframes fadeInTop{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInBottom{0%{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingItemComponent, decorators: [{
type: Component,
args: [{ selector: 'rosen-onboarding-item', encapsulation: ViewEncapsulation.None, standalone: false, template: "<div #container class=\"onboarding-item\" [ngStyle]=\"getStyle()\">\n <div class=\"onboarding-item-header text-color animated script-font fade-in-left\" ngClass=\"getTextAlignClass()\">\n {{getHeadline()}}\n </div>\n <div class=\"onboarding-item-details text-color animated regular-font fade-in-right\" ngClass=\"getTextAlignClass()\">\n {{getDetails()}}\n </div>\n</div>\n", styles: [".onboarding-item{position:absolute}.onboarding-item .text-color{color:#fff}.onboarding-item .onboarding-item-header{font-size:24px;text-align:center}.onboarding-item .onboarding-item-details{font-size:14px;text-align:center}.onboarding-item .align-left{text-align:left}.onboarding-item .align-right{text-align:right}.onboarding-item .animated{animation-duration:1s}.onboarding-item .fade-in-right{animation-name:fadeInRight}.onboarding-item .fade-in-left{animation-name:fadeInLeft}.onboarding-item .fade-in-top{animation-name:fadeInTop}.onboarding-item .fade-in-bottom{animation-name:fadeInBottoim}@keyframes fadeInRight{0%{opacity:0;transform:translate(-20px)}to{opacity:1;transform:translate(0)}}@keyframes fadeInLeft{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}@keyframes fadeInTop{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInBottom{0%{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}\n"] }]
}], ctorParameters: () => [{ type: TranslatorBaseService }, { type: WindowRef }], propDecorators: { item: [{
type: Input
}], container: [{
type: ViewChild,
args: ['container', { static: true }]
}] } });
/**
* Main component of the onboarding module.
* Handles the visualization of the onboarding items
*/
class OnboardingComponent {
constructor(onboardingService, domSanitizer) {
this.onboardingService = onboardingService;
this.domSanitizer = domSanitizer;
this.visibleItem = null;
const config = onboardingService.getConfiguration();
this.textConfig = config.textConfiguration;
this.buttonConfig = config.buttonsConfiguration;
if (config.iconConfiguration) { // we expect the config to be present always but just in case
this.matIconName = config.iconConfiguration.matIconName;
this.fontSet = config.iconConfiguration.fontSet;
this.fontIcon = config.iconConfiguration.fontIcon;
this.svgIcon = config.iconConfiguration.svgIcon;
}
}
ngOnInit() {
// Dynamic generated css is needed because these options have be configurable
let dynCss = ``;
// for this component
dynCss += `<style type="text/css">`;
dynCss += `.onboarding-component-container .script-font { font-family: ${this.textConfig.scriptFontFamily}}`;
dynCss += `.onboarding-component-container .regular-font { font-family: ${this.textConfig.regularFontFamily}}`;
dynCss += `</style>`;
this.dynamicCss = this.domSanitizer.bypassSecurityTrustHtml(dynCss);
}
ngAfterViewInit() {
this.visibleItemsChangedSubscription = this.onboardingService.visibleItemsChanged.subscribe(() => {
this.visibleItem = this.onboardingService.visibleItems.currentItem;
this.hasNext = this.onboardingService.visibleItems.hasNext;
if (this.visibleItem) {
this.showItem(this.visibleItem);
}
});
}
ngOnDestroy() {
if (this.visibleItemsChangedSubscription) {
this.visibleItemsChangedSubscription.unsubscribe();
}
this.onboardingService.hide(); // hide ALL items
}
/**
* gets the fixed position of the html element
* used by template to set the position of the spotlight
*/
getPositionStyle(ele) {
const pos = OnboardingHtmlElementHelper.getPosition(ele);
const style = {
position: 'fixed',
left: pos.x + 'px',
top: pos.y + 'px',
width: pos.width + 'px',
height: pos.height + 'px'
};
if (pos.fixed) {
style.background = 'transparent';
}
return style;
}
isSpotlightTransparent(item) {
return item.transparentSpotlight;
}
/**
* used by turn off button in template
*/
disable() {
if (this.visibleItem) {
this.hideItem(this.visibleItem); // hide old item
}
this.onboardingService.disable();
}
/**
* hide current group (show next one if one is available
*/
hide() {
if (this.onboardingService.visibleItems && this.hasNext) {
// hide current and show next item
this.hideItem(this.visibleItem); // hide OLD items
this.visibleItem = this.onboardingService.visibleItems.nextItem();
this.hasNext = this.onboardingService.visibleItems.hasNext; // show NEW ones
this.showItem(this.visibleItem);
}
else {
this.hideItem(this.visibleItem);
this.onboardingService.hide(); // mark all items as seen...
this.visibleItem = null;
this.hasNext = false;
}
}
buttonsPositionStyle() {
switch (this.buttonConfig.position) {
case OnboardingButtonsPosition.Bottom:
return {
bottom: this.buttonConfig.verticalDistanceToBorderInPx + 'px',
left: '50%',
transform: 'translateX(-50%)',
};
case OnboardingButtonsPosition.BottomLeft:
return {
bottom: this.buttonConfig.verticalDistanceToBorderInPx + 'px',
left: this.buttonConfig.horizontalDistanceToBorderInPx + 'px',
};
case OnboardingButtonsPosition.Left:
return {
top: '50%',
transform: 'translateY(-50%)',
left: this.buttonConfig.horizontalDistanceToBorderInPx + 'px'
};
case OnboardingButtonsPosition.TopLeft:
return {
top: this.buttonConfig.verticalDistanceToBorderInPx + 'px',
left: this.buttonConfig.horizontalDistanceToBorderInPx + 'px'
};
case OnboardingButtonsPosition.Top:
return {
top: this.buttonConfig.verticalDistanceToBorderInPx + 'px',
left: '50%',
transform: 'translateX(-50%)',
};
case OnboardingButtonsPosition.TopRight:
return {
top: this.buttonConfig.verticalDistanceToBorderInPx + 'px',
right: this.buttonConfig.horizontalDistanceToBorderInPx + 'px'
};
case OnboardingButtonsPosition.Right:
return {
top: '50%',
transform: 'translateY(-50%)',
right: this.buttonConfig.horizontalDistanceToBorderInPx + 'px'
};
case OnboardingButtonsPosition.BottomRight:
default:
return {
bottom: this.buttonConfig.verticalDistanceToBorderInPx + 'px',
right: this.buttonConfig.horizontalDistanceToBorderInPx + 'px'
};
}
}
/**
* Show onboarding item
*/
showItem(i) {
if (this.onboardingService.isEnabled()) {
i.element.classList.add('onboarding-highlighted');
if (!i.element.style.position || i.element.style.position === 'static') {
i.element.classList.add('onboarding-highlighted-on-static');
}
}
}
/**
* Hide SINGLE element without change notification
*/
hideItem(i) {
i.element.classList.remove('onboarding-highlighted');
i.element.classList.remove('onboarding-highlighted-on-static');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingComponent, deps: [{ token: OnboardingService }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: OnboardingComponent, isStandalone: false, selector: "rosen-onboarding", ngImport: i0, template: "<span [innerHtml]=\"dynamicCss\"></span>\n\n<div class=\"onboarding-component-container\" *ngIf=\"onboardingService.isEnabled() && visibleItem\">\n <div class=\"onboarding-header script-font\" *ngIf=\"onboardingService.isEnabled() && visibleItem\">\n <mat-icon *ngIf=\"matIconName && !svgIcon && !fontSet\">{{matIconName}}</mat-icon>\n <mat-icon *ngIf=\"svgIcon || fontSet\" [svgIcon]=\"svgIcon\" [fontSet]=\"fontSet\" [fontIcon]=\"fontIcon\"></mat-icon>\n {{'ONBOARDING' |translate|uppercase}}\n </div>\n <div class=\"onboarding-shadow\"\n [ngStyle]=\"getPositionStyle(visibleItem.element)\"></div>\n <div class=\"onboarding-spotlight\"\n [class.onboarding-spotlight-transparent]=\"isSpotlightTransparent(visibleItem.item)\"\n [ngStyle]=\"getPositionStyle(visibleItem.element)\"></div>\n <div class=\"onboarding-items\">\n <div *ngFor=\"let currentItem of onboardingService.visibleItems.allItems\">\n <rosen-onboarding-item [item]=\"currentItem\" *ngIf=\"currentItem === visibleItem\"></rosen-onboarding-item>\n </div>\n </div>\n <div class=\"onboarding-overlay\" (click)=\"hide()\"></div>\n <div class=\"onboarding-buttons\" [ngStyle]=\"buttonsPositionStyle()\">\n <button mat-flat-button color=\"warn\" (click)=\"disable()\">\n <span>{{'ONBOARDING_DO_NOT_SHOW_AGAIN_MSG' |translate}}</span>\n </button>\n <button mat-flat-button color=\"primary\" (click)=\"hide()\">\n <span *ngIf=\"!hasNext\">{{'ONBOARDING_GOT_IT_MSG' |translate}}</span>\n <span *ngIf=\"hasNext\">{{'ONBOARDING_NEXT_MSG' | translate}}</span>\n </button>\n </div>\n</div>\n", styles: [".onboarding-component-container .mat-icon{font-size:32px;width:32px!important;height:32px!important;line-height:32px!important}.onboarding-component-container .onboarding-shadow{box-shadow:0 0 0 10000px #000000b3;z-index:9999994}.onboarding-component-container .onboarding-spotlight{box-shadow:0 0 8px 8px #fff;background:#fff;z-index:9999995}.onboarding-component-container .onboarding-spotlight-transparent{background:transparent}.onboarding-component-container .onboarding-items{position:fixed;inset:0;z-index:9999997}.onboarding-component-container .onboarding-overlay{position:fixed;inset:0;z-index:9999998}.onboarding-component-container .onboarding-buttons{position:fixed;z-index:9999999;clear:both}.onboarding-component-container .onboarding-buttons>button{float:right}.onboarding-component-container .onboarding-buttons button[color=primary]{margin-right:8px}.onboarding-component-container .onboarding-header{position:fixed;inset:4px 0 0 4px;z-index:9999998;font-size:24px;color:#d9d9d9}.onboarding-component-container .onboarding-header>span{font-size:24px}.onboarding-highlighted,.onboarding-highlighted *{z-index:9999996!important}.onboarding-highlighted *.glyphicon,.onboarding-highlighted a,a.onboarding-highlighted{color:#444!important}.onboarding-highlighted-on-static{position:relative}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3$1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: OnboardingItemComponent, selector: "rosen-onboarding-item", inputs: ["item"] }, { kind: "pipe", type: i3.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: PrimitiveTranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingComponent, decorators: [{
type: Component,
args: [{ selector: 'rosen-onboarding', encapsulation: ViewEncapsulation.None, standalone: false, template: "<span [innerHtml]=\"dynamicCss\"></span>\n\n<div class=\"onboarding-component-container\" *ngIf=\"onboardingService.isEnabled() && visibleItem\">\n <div class=\"onboarding-header script-font\" *ngIf=\"onboardingService.isEnabled() && visibleItem\">\n <mat-icon *ngIf=\"matIconName && !svgIcon && !fontSet\">{{matIconName}}</mat-icon>\n <mat-icon *ngIf=\"svgIcon || fontSet\" [svgIcon]=\"svgIcon\" [fontSet]=\"fontSet\" [fontIcon]=\"fontIcon\"></mat-icon>\n {{'ONBOARDING' |translate|uppercase}}\n </div>\n <div class=\"onboarding-shadow\"\n [ngStyle]=\"getPositionStyle(visibleItem.element)\"></div>\n <div class=\"onboarding-spotlight\"\n [class.onboarding-spotlight-transparent]=\"isSpotlightTransparent(visibleItem.item)\"\n [ngStyle]=\"getPositionStyle(visibleItem.element)\"></div>\n <div class=\"onboarding-items\">\n <div *ngFor=\"let currentItem of onboardingService.visibleItems.allItems\">\n <rosen-onboarding-item [item]=\"currentItem\" *ngIf=\"currentItem === visibleItem\"></rosen-onboarding-item>\n </div>\n </div>\n <div class=\"onboarding-overlay\" (click)=\"hide()\"></div>\n <div class=\"onboarding-buttons\" [ngStyle]=\"buttonsPositionStyle()\">\n <button mat-flat-button color=\"warn\" (click)=\"disable()\">\n <span>{{'ONBOARDING_DO_NOT_SHOW_AGAIN_MSG' |translate}}</span>\n </button>\n <button mat-flat-button color=\"primary\" (click)=\"hide()\">\n <span *ngIf=\"!hasNext\">{{'ONBOARDING_GOT_IT_MSG' |translate}}</span>\n <span *ngIf=\"hasNext\">{{'ONBOARDING_NEXT_MSG' | translate}}</span>\n </button>\n </div>\n</div>\n", styles: [".onboarding-component-container .mat-icon{font-size:32px;width:32px!important;height:32px!important;line-height:32px!important}.onboarding-component-container .onboarding-shadow{box-shadow:0 0 0 10000px #000000b3;z-index:9999994}.onboarding-component-container .onboarding-spotlight{box-shadow:0 0 8px 8px #fff;background:#fff;z-index:9999995}.onboarding-component-container .onboarding-spotlight-transparent{background:transparent}.onboarding-component-container .onboarding-items{position:fixed;inset:0;z-index:9999997}.onboarding-component-container .onboarding-overlay{position:fixed;inset:0;z-index:9999998}.onboarding-component-container .onboarding-buttons{position:fixed;z-index:9999999;clear:both}.onboarding-component-container .onboarding-buttons>button{float:right}.onboarding-component-container .onboarding-buttons button[color=primary]{margin-right:8px}.onboarding-component-container .onboarding-header{position:fixed;inset:4px 0 0 4px;z-index:9999998;font-size:24px;color:#d9d9d9}.onboarding-component-container .onboarding-header>span{font-size:24px}.onboarding-highlighted,.onboarding-highlighted *{z-index:9999996!important}.onboarding-highlighted *.glyphicon,.onboarding-highlighted a,a.onboarding-highlighted{color:#444!important}.onboarding-highlighted-on-static{position:relative}\n"] }]
}], ctorParameters: () => [{ type: OnboardingService }, { type: i2.DomSanitizer }] });
/**
* Unique key to identify the seen onboarding items in the local storage
*/
const seenSelectorsLocalStorageKey = '894ae732-b4bd-45c9-b543-6f9c5c5a86b6';
/**
* Stores the seen onboarding items to the local storage
*
* If you want to implement an own service to store the data e.g. in a database you can extend
* your own service from theSeenSelectorsBaseService and use the provide feature in your app.module with
* {provide: SeenSelectorsBaseService, useClass: YourOwnSeenSelectorsService}
*/
class LocalStorageSeenSelectorsService extends SeenSelectorsBaseService {
constructor(errorHandler) {
super();
this.errorHandler = errorHandler;
}
/**
* loads seen items from localStorage
* @returns string array of all seen selectors
*/
load() {
const seenSelectorsString = localStorage.getItem(seenSelectorsLocalStorageKey);
if (seenSelectorsString?.length > 0) {
try {
return of(JSON.parse(seenSelectorsString));
}
catch (error) {
this.errorHandler.handleError(error);
}
}
return of([]);
}
/**
* save items to localStorage
* @returns success of the operation (true = good, false = failed)
*/
save(seenSelectors) {
try {
localStorage.setItem(seenSelectorsLocalStorageKey, JSON.stringify(seenSelectors));
}
catch (error) {
this.errorHandler.handleError(error);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: LocalStorageSeenSelectorsService, deps: [{ token: i0.ErrorHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: LocalStorageSeenSelectorsService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: LocalStorageSeenSelectorsService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i0.ErrorHandler }] });
/**
* Unique key to identify the onboarding enabled status in the local storage
*/
const enabledLocalStorageKey = '42cfe10a-c2d3-42ba-9c55-6198545a0c49';
/**
* Stores the enabled status of the onboarding to the local storage
*
* If you want to implement an own service to store the data e.g. in a database you can extend your own service
* from the EnabledStatusBaseService and use the provide feature in your app.module with
* {provide: EnabledStatusBaseService, useClass: YourOwnEnabledStatusService}
*/
class LocalStorageEnabledStatusService extends EnabledStatusBaseService {
constructor(errorHandler) {
super();
this.errorHandler = errorHandler;
}
/**
* loads the status from the persistent storage
* @returns status (true = enabled, false = disabled)
*/
load() {
try {
return of('true' === localStorage.getItem(enabledLocalStorageKey));
}
catch (error) {
this.errorHandler.handleError(error);
}
return of(true);
}
/**
* saves the status to localStorage
* @returns success of the operation (true = good, false = failed)
*/
save(enabled) {
try {
localStorage.setItem(enabledLocalStorageKey, enabled ? 'true' : 'false');
}
catch (error) {
this.errorHandler.handleError(error);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: LocalStorageEnabledStatusService, deps: [{ token: i0.ErrorHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: LocalStorageEnabledStatusService, providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: LocalStorageEnabledStatusService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }]
}], ctorParameters: () => [{ type: i0.ErrorHandler }] });
/**
* Service for the translations of internal text
*/
class BuildInTranslatorService extends TranslatorBaseService {
constructor() {
super(...arguments);
/**
* An EventEmitter to listen to lang change events.
* A LangChangeEvent is an object with the minimium properties lang: string (where lang is the new language code)
*/
this.onLangChange = new EventEmitter();
this.translations = {
'ONBOARDING': 'Onboarding',
'ONBOARDING_FAILED_TO_LOAD_USER_SETTINGS': 'Failed to load onboarding settings.',
'ONBOARDING_FAILED_TO_SAVE_USER_SETTINGS': 'Failed to save onboarding settings.',
'ONBOARDING_GOT_IT_MSG': 'Got it',
'ONBOARDING_DO_NOT_SHOW_AGAIN_MSG': 'Turn off',
'ONBOARDING_NEXT_MSG': 'Next',
'ONBOARDING_ENABLE': 'Turn on',
'ONBOARDING_DISABLE': 'Turn off',
'ONBOARDING_CLEAR': 'Reset'
};
}
/**
* The language (code) currently used
*/
get currentLang() {
return 'en';
}
/**
* Returns a translation instantly from the internal state of loaded translation.
*/
instant(key) {
const text = this.translations[key];
if (typeof text === 'string') {
return text;
}
return key;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BuildInTranslatorService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BuildInTranslatorService, providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: BuildInTranslatorService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' /* makes sure that service stays a single instance among seperate modules */ }]
}] });
/**
* Module for ngx-onboarding.
* Import this into your "main" module e.g. AppModule
*/
class OnboardingModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: OnboardingModule, declarations: [OnboardingComponent,
OnboardingItemComponent,
OnboardingButtonComponent,
PrimitiveTranslatePipe], imports: [CommonModule,
MatButtonModule,
MatBadgeModule,
MatIconModule,
MatMenuModule], exports: [OnboardingComponent,
OnboardingButtonComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingModule, providers: [
BrowserDOMSelectorService,
WindowRef,
{
provide: SeenSelectorsBaseService, useClass: LocalStorageSeenSelectorsService
},
{
provide: EnabledStatusBaseService, useClass: LocalStorageEnabledStatusService
},
{
provide: TranslatorBaseService, useClass: BuildInTranslatorService
},
provideHttpClient(withInterceptorsFromDi())
], imports: [CommonModule,
MatButtonModule,
MatBadgeModule,
MatIconModule,
MatMenuModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: OnboardingModule, decorators: [{
type: NgModule,
args: [{ declarations: [
OnboardingComponent,
OnboardingItemComponent,
OnboardingButtonComponent,
PrimitiveTranslatePipe
],
exports: [
OnboardingComponent,
OnboardingButtonComponent
], imports: [CommonModule,
MatButtonModule,
MatBadgeModule,
MatIconModule,
MatMenuModule], providers: [
BrowserDOMSelectorService,
WindowRef,
{
provide: SeenSelectorsBaseService, useClass: LocalStorageSeenSelectorsService
},
{
provide: EnabledStatusBaseService, useClass: LocalStorageEnabledStatusService
},
{
provide: TranslatorBaseService, useClass: BuildInTranslatorService
},
provideHttpClient(withInterceptorsFromDi())
] }]
}] });
/*
* Public API Surface of ngx-onboarding
*/
/**
* Generated bundle index. Do not edit.
*/
export { EnabledStatusBaseService, OnboardingButtonComponent, OnboardingButtonsPosition, OnboardingComponent, OnboardingItem, OnboardingModule, OnboardingService, SeenSelectorsBaseService, TranslatorBaseService };
//# sourceMappingURL=rosen-group-ngx-onboarding.mjs.map