@open-rlb/ng-app 3.1.122 → 3.1.123

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,6 +37,7 @@ const RLB_CFG_AUTH = new InjectionToken(`${RLB_CFG}:auth`);
37
37
  const RLB_APP_NAVCOMP = new InjectionToken(`rlb.app.navcomp`);
38
38
  const RLB_APP_SIDEBARCOMP = new InjectionToken(`rlb.app.sidebarcomp`);
39
39
  const RLB_CFG_ACL = new InjectionToken(`${RLB_CFG}:acl`);
40
+ const RLB_NAV_SURFACE = new InjectionToken('rlb.nav.surface');
40
41
  const RLB_AUTH_URL_HANDLER = new InjectionToken('rlb.auth.urlHandler');
41
42
 
42
43
  class TokenCookiesService {
@@ -344,6 +345,7 @@ const NavbarActions = createActionGroup({
344
345
  SetSearchText: props(),
345
346
  SetLeftItems: props(),
346
347
  SetRightItems: props(),
348
+ SetMobileItems: props(),
347
349
  SetLoginVisible: props(),
348
350
  SetSettingsVisible: props(),
349
351
  SetAppsVisible: props(),
@@ -360,6 +362,7 @@ const initialNavbarState = {
360
362
  searchText: null,
361
363
  leftItems: [],
362
364
  rightItems: [],
365
+ mobileItems: [],
363
366
  loginVisible: false,
364
367
  settingsVisible: false,
365
368
  appsVisible: false,
@@ -2297,6 +2300,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
2297
2300
  }]
2298
2301
  }] });
2299
2302
 
2303
+ class MobileComponentPipe {
2304
+ constructor() {
2305
+ this.config = inject(RLB_APP_NAVCOMP);
2306
+ }
2307
+ transform(value) {
2308
+ const slot = this.config.mobile ?? this.config.right;
2309
+ const t = slot.find(c => c.name === value)?.component;
2310
+ if (!t) {
2311
+ throw new Error(`No component found for name ${value}`);
2312
+ }
2313
+ return t;
2314
+ }
2315
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MobileComponentPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
2316
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.19", ngImport: i0, type: MobileComponentPipe, isStandalone: true, name: "mobileComponent" }); }
2317
+ }
2318
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: MobileComponentPipe, decorators: [{
2319
+ type: Pipe,
2320
+ args: [{
2321
+ name: 'mobileComponent',
2322
+ }]
2323
+ }] });
2324
+
2300
2325
  class SidebarFooterComponentPipe {
2301
2326
  constructor() {
2302
2327
  this.config = inject(RLB_APP_SIDEBARCOMP);
@@ -2391,6 +2416,17 @@ class AppTemplateComponent {
2391
2416
  this.appsService = inject(AppsService);
2392
2417
  this.authService = inject(AuthenticationService);
2393
2418
  this.router = inject(Router);
2419
+ this.injector = inject(Injector);
2420
+ // Lets one custom component serve both chrome surfaces: it injects RLB_NAV_SURFACE
2421
+ // (optional) and lays itself out accordingly.
2422
+ this.navbarSurfaceInjector = Injector.create({
2423
+ providers: [{ provide: RLB_NAV_SURFACE, useValue: 'navbar' }],
2424
+ parent: this.injector,
2425
+ });
2426
+ this.mobileSurfaceInjector = Injector.create({
2427
+ providers: [{ provide: RLB_NAV_SURFACE, useValue: 'mobile-menu' }],
2428
+ parent: this.injector,
2429
+ });
2394
2430
  this.sidebarVisible = this.store.selectSignal((state) => state[sidebarsFeatureKey].visible);
2395
2431
  this.sidearHasLogin = this.store.selectSignal((state) => state[sidebarsFeatureKey].loginVisible);
2396
2432
  this.sidearHasSearch = this.store.selectSignal((state) => state[sidebarsFeatureKey].searchVisible);
@@ -2403,6 +2439,7 @@ class AppTemplateComponent {
2403
2439
  this.navHeader = this.store.selectSignal((state) => state[navbarsFeatureKey].header);
2404
2440
  this.navLeftItems = this.store.selectSignal((state) => state[navbarsFeatureKey].leftItems);
2405
2441
  this.navRightItems = this.store.selectSignal((state) => state[navbarsFeatureKey].rightItems);
2442
+ this.navMobileItems = this.store.selectSignal((state) => state[navbarsFeatureKey].mobileItems);
2406
2443
  this.navbarHasLogin = this.store.selectSignal((state) => state[navbarsFeatureKey].loginVisible);
2407
2444
  this.navbarHasSettings = this.store.selectSignal((state) => state[navbarsFeatureKey].settingsVisible);
2408
2445
  this.navbarHasApps = this.store.selectSignal(state => state[navbarsFeatureKey].appsVisible);
@@ -2412,6 +2449,10 @@ class AppTemplateComponent {
2412
2449
  this.userInfo = toSignal(this.authService.userInfo$, { initialValue: null });
2413
2450
  this.theme = this.store.selectSignal(state => state[appContextFeatureKey].theme);
2414
2451
  this.apps = computed(() => this.appsService.apps().filter((app) => app.enabled && app.id), ...(ngDevMode ? [{ debugName: "apps" }] : /* istanbul ignore next */ []));
2452
+ /** Mirrors the mobile offcanvas body: false means the panel would render empty. */
2453
+ this.mobileMenuHasContent = computed(() => this.navMobileItems().length > 0 ||
2454
+ (this.navbarHasApps() && this.apps().length > 1) ||
2455
+ this.navbarHasSettings(), ...(ngDevMode ? [{ debugName: "mobileMenuHasContent" }] : /* istanbul ignore next */ []));
2415
2456
  this.router.events
2416
2457
  .pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed())
2417
2458
  .subscribe(() => {
@@ -2447,7 +2488,7 @@ class AppTemplateComponent {
2447
2488
  this.mobileOffcanvas()?.close();
2448
2489
  }
2449
2490
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: AppTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2450
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: AppTemplateComponent, isStandalone: true, selector: "rlb-app-template", inputs: { modalContainerId: { classPropertyName: "modalContainerId", publicName: "modal-container-id", isSignal: true, isRequired: true, transformFunction: null }, breadcrumbInput: { classPropertyName: "breadcrumbInput", publicName: "breadcrumb", isSignal: true, isRequired: false, transformFunction: null }, toastContainerIds: { classPropertyName: "toastContainerIds", publicName: "toast-container-ids", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "mobileOffcanvas", first: true, predicate: ["mobileOffcanvas"], descendants: true, isSignal: true }, { propertyName: "mobileSettingsMenu", first: true, predicate: ["mobileSettingsMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"rlb-app\">\n @if (navVisible()) {\n <rlb-navbar [dark]=\"theme() === 'dark'\" [showSideBarToggler]=\"sidebarVisible()\" expand=\"lg\" class=\"border-bottom py-1 rlb-navbar\">\n @if (navHeader(); as header) {\n <a rlb-navbar-brand href=\"#\">\n\n @if (header.type === 'text') {\n {{ header.text }}\n }\n\n @if (header.type === 'image') {\n <img\n [src]=\"header.src\"\n [alt]=\"header.alt ?? 'Brand'\"\n [height]=\"header.height ?? 40\"\n />\n }\n </a>\n }\n @if (navSearchVisible()) {\n <rlb-navbar-form>\n <rlb-input-group class=\"my-1 mx-3\" validate>\n <rlb-input type=\"search\" class=\"search-input\" placeholder=\"Search\" [(ngModel)]=\"navSearchText\"\n (keyup.enter)=\"setNavbarSearchText(navSearchText)\" name=\"search\" size=\"small\">\n <button after rlb-button outline type=\"submit\" (click)=\"setNavbarSearchText(navSearchText)\" size=\"sm\">\n <i class=\"bi bi-search\"></i>\n </button>\n </rlb-input>\n </rlb-input-group>\n </rlb-navbar-form>\n }\n\n <!-- MOBILE VIEWS -->\n <div rlb-custom-navbar-items class=\"d-flex d-lg-none\">\n @if (isAuthenticated()) {\n <rlb-fab size=\"sm\" outline toggle=\"offcanvas\" toggle-target=\"mobileMenuOffcanvas\">\n <i class=\"bi bi-three-dots-vertical\"></i>\n </rlb-fab>\n\n <rlb-offcanvas\n #mobileOffcanvas\n id=\"mobileMenuOffcanvas\"\n [placement]=\"'end'\"\n (statusChange)=\"onMobileMenuStatusChange($event)\"\n >\n <rlb-offcanvas-header class=\"border-bottom\">\n <h5 rlb-offcanvas-title class=\"fw-bold mb-0\">Menu</h5>\n </rlb-offcanvas-header>\n\n <rlb-offcanvas-body class=\"p-0 overflow-x-hidden\">\n\n <!-- Mobile Apps Grid -->\n @if (navbarHasApps() && apps().length > 1) {\n <div class=\"border-bottom pb-2\">\n <rlb-app-dropdown-selector\n mode=\"mobile\"\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n </div>\n }\n\n <!-- Mobile Settings Carousel -->\n @if (isAuthenticated() || navbarHasSettings()) {\n <div class=\"pt-2\">\n <rlb-settings-dropdown-selector\n mode=\"mobile\"\n #mobileSettingsMenu\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n </div>\n }\n\n </rlb-offcanvas-body>\n </rlb-offcanvas>\n } @else {\n <rlb-fab size=\"sm\" (click)=\"loginNav($event)\" [tooltip]=\"('core.account.login') |translate\">\n <i class=\" bi bi-box-arrow-in-left\"></i>\n </rlb-fab>\n }\n\n </div>\n\n <rlb-navbar-items>\n @for (navComponent of navLeftItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container *ngComponentOutlet=\"navComponent | leftComponent\"></ng-container>\n </ng-container>\n }\n </rlb-navbar-items>\n\n <rlb-navbar-items class=\"ms-auto align-items-center\">\n @for (navComponent of navRightItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container *ngComponentOutlet=\"navComponent | rightComponent\"></ng-container>\n </ng-container>\n }\n @if (separatorVisible() && isAuthenticated()) {\n <rlb-navbar-separator />\n }\n\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n @if (navbarLayout() == 'default') {\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.account.login') |translate\">\n <i class=\" bi bi-box-arrow-in-left\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.account.login' | translate}}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasLogin() && isAuthenticated()) {\n <rlb-navbar-item [router-link]=\"'/profile'\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.account.title') |translate\">\n <i class=\"bi bi-person\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.account.title' | translate}}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasSettings()) {\n <rlb-navbar-item [router-link]=\"'/settings'\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.settings.title') |translate\">\n <i class=\"bi bi-gear\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.settings.title' | translate}}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasApps() && apps().length > 1) {\n <rlb-navbar-item [router-link]=\"'/apps'\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.apps.button') |translate\">\n <i class=\"bi bi-grid-3x3-gap-fill\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.apps.button' | translate}}</span>\n </rlb-navbar-item>\n }\n\n } @else if (navbarLayout() == 'dropdown') {\n <!-- MODERN DROPDOWN MODE -->\n\n <!--Unauthenticated Login -->\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.account.login') | translate\">\n <i class=\"bi bi-box-arrow-in-left fs-5\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.login' | translate }}</span>\n </rlb-navbar-item>\n }\n\n <!-- Profile & Settings Account Card -->\n @if (navbarHasSettings() && isAuthenticated()) {\n <rlb-settings-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n }\n\n <!-- Apps Launcher -->\n @if (navbarHasApps() && isAuthenticated() && apps().length > 1) {\n <rlb-app-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n }\n }\n </ng-container>\n </rlb-navbar-items>\n </rlb-navbar>\n }\n <div class=\"rlb-main-wrapper\">\n @if (sidebarVisible()) {\n <rlb-sidebar [dark]=\"theme() === 'dark'\" id=\"sidebar\" class=\"rlb-sidebar\">\n @for (item of sidebarItems(); track $index) {\n <rlb-sidebar-item\n *roles=\"item.action\"\n [icon]=\"item.icon\" [link]=\"item.url\"\n [title]=\"item.title\" [label]=\"item.label\"\n [badgeCounter]=\"item.badgeCounter\"\n (click)=\"onSideBarItemClick(item)\"\n >\n {{item.label}}\n @for (subitem of item.items || []; track $index) {\n <rlb-sidebar-item\n *roles=\"subitem.action\"\n [icon]=\"subitem.icon\"\n [link]=\"subitem.url\"\n [title]=\"subitem.title\"\n [label]=\"subitem.label\"\n [badgeCounter]=\"subitem.badgeCounter\"\n (click)=\"onSideBarItemClick(subitem)\"\n >\n {{subitem.label}}\n </rlb-sidebar-item>\n }\n </rlb-sidebar-item>\n }\n @if (sidebarFooter(); as footerName) {\n <div rlb-sidebar-footer class=\"mt-auto\">\n <ng-container *ngComponentOutlet=\"footerName | sidebarFooterComponent\"></ng-container>\n </div>\n }\n </rlb-sidebar>\n }\n <div class=\"rlb-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!--@if (modalContainerId()) {-->\n<!-- <rlb-modal-container [id]=\"modalContainerId()\" />-->\n<!--}-->\n\n<!--@if (toastContainerIds()) {-->\n<!-- @if (Array.isArray(toastContainerIds())) {-->\n<!-- @for (toastContainerId of toastContainerIds() | asMulti; track toastContainerId) {-->\n<!-- <rlb-toast-container [id]=\"toastContainerId\" />-->\n<!-- }-->\n<!-- } @else {-->\n<!-- <rlb-toast-container class=\"position-fixed bottom-0 end-0 p-3\" [id]=\"toastContainerIds() | asSingle\" />-->\n<!-- }-->\n<!--}-->\n", styles: [".separator{border-left:1px solid;padding:0 2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$6.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: NavbarComponent, selector: "rlb-navbar", inputs: ["dark", "showSideBarToggler", "color", "placement", "expand", "class", "enable-dropdown-toggler"] }, { kind: "directive", type: NavbarBrandDirective, selector: "[rlb-navbar-brand]" }, { kind: "component", type: NavbarFormComponent, selector: "rlb-navbar-form", inputs: ["role", "class"] }, { kind: "component", type: NavbarItemsComponent, selector: "rlb-navbar-items", inputs: ["scroll", "class"], outputs: ["click"] }, { kind: "component", type: NavbarItemComponent, selector: "rlb-navbar-item", inputs: ["disabled", "router-link", "class"], outputs: ["click"] }, { kind: "component", type: NavbarSeparatorComponent, selector: "rlb-navbar-separator", inputs: ["class"] }, { kind: "component", type: SidebarComponent, selector: "rlb-sidebar", inputs: ["dark", "rounded"] }, { kind: "component", type: SidebarItemComponent, selector: "rlb-sidebar-item", inputs: ["title", "icon", "label", "link", "badgeCounter"], outputs: ["click"] }, { kind: "component", type: OffcanvasComponent, selector: "rlb-offcanvas", inputs: ["id", "body-scroll", "scroll-backup", "close-manual", "placement", "responsive"], outputs: ["statusChange"] }, { kind: "component", type: OffcanvasHeaderComponent, selector: "rlb-offcanvas-header", inputs: ["offcanvasId"] }, { kind: "component", type: OffcanvasBodyComponent, selector: "rlb-offcanvas-body" }, { kind: "component", type: RlbFabComponent, selector: "rlb-fab", inputs: ["color", "size", "disabled", "outline", "position"] }, { kind: "component", type: InputGroupComponent, selector: "rlb-input-group", inputs: ["text", "validate", "size"] }, { kind: "component", type: InputComponent, selector: "rlb-input", inputs: ["disabled", "readonly", "placeholder", "type", "size", "name", "max", "min", "step", "date-type", "timezone", "inputId", "extValidation", "enable-validation"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip]", inputs: ["tooltip", "tooltip-placement", "tooltip-class", "tooltip-html"] }, { kind: "directive", type: RlbRole, selector: "[roles]", inputs: ["roles"] }, { kind: "component", type: AppDropdownSelectorComponent, selector: "rlb-app-dropdown-selector", inputs: ["mode", "apps", "isAuthenticated"], outputs: ["appSelected"] }, { kind: "component", type: SettingsDropdownSelectorComponent, selector: "rlb-settings-dropdown-selector", inputs: ["mode", "apps", "isAuthenticated"], outputs: ["appSelected"] }, { kind: "component", type: ButtonComponent, selector: "button[rlb-button], a[rlb-button]", inputs: ["color", "size", "disabled", "outline", "isLink"] }, { kind: "directive", type: ToggleDirective, selector: " button[toggle], a[toggle], rlb-navbar-item[toggle], rlb-button-toolbar[toggle], rlb-fab[toggle],", inputs: ["toggle", "toggle-target", "collapsed", "auto-close"] }, { kind: "pipe", type: i1$4.TranslatePipe, name: "translate" }, { kind: "pipe", type: LeftComponentPipe, name: "leftComponent" }, { kind: "pipe", type: RightComponentPipe, name: "rightComponent" }, { kind: "pipe", type: SidebarFooterComponentPipe, name: "sidebarFooterComponent" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2491
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: AppTemplateComponent, isStandalone: true, selector: "rlb-app-template", inputs: { modalContainerId: { classPropertyName: "modalContainerId", publicName: "modal-container-id", isSignal: true, isRequired: true, transformFunction: null }, breadcrumbInput: { classPropertyName: "breadcrumbInput", publicName: "breadcrumb", isSignal: true, isRequired: false, transformFunction: null }, toastContainerIds: { classPropertyName: "toastContainerIds", publicName: "toast-container-ids", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "mobileOffcanvas", first: true, predicate: ["mobileOffcanvas"], descendants: true, isSignal: true }, { propertyName: "mobileSettingsMenu", first: true, predicate: ["mobileSettingsMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"rlb-app\">\n @if (navVisible()) {\n <rlb-navbar\n [dark]=\"theme() === 'dark'\"\n [showSideBarToggler]=\"sidebarVisible()\"\n expand=\"lg\"\n class=\"border-bottom py-1 rlb-navbar\"\n >\n @if (navHeader(); as header) {\n <a\n rlb-navbar-brand\n href=\"#\"\n >\n @if (header.type === 'text') {\n {{ header.text }}\n }\n\n @if (header.type === 'image') {\n <img\n [src]=\"header.src\"\n [alt]=\"header.alt ?? 'Brand'\"\n [height]=\"header.height ?? 40\"\n />\n }\n </a>\n }\n @if (navSearchVisible()) {\n <rlb-navbar-form>\n <rlb-input-group\n class=\"my-1 mx-3\"\n validate\n >\n <rlb-input\n type=\"search\"\n class=\"search-input\"\n placeholder=\"Search\"\n [(ngModel)]=\"navSearchText\"\n (keyup.enter)=\"setNavbarSearchText(navSearchText)\"\n name=\"search\"\n size=\"small\"\n >\n <button\n after\n rlb-button\n outline\n type=\"submit\"\n (click)=\"setNavbarSearchText(navSearchText)\"\n size=\"sm\"\n >\n <i class=\"bi bi-search\"></i>\n </button>\n </rlb-input>\n </rlb-input-group>\n </rlb-navbar-form>\n }\n\n <!-- MOBILE VIEWS -->\n <div\n rlb-custom-navbar-items\n class=\"d-flex d-lg-none\"\n >\n @if (isAuthenticated()) {\n <!-- No toggler when the panel would render empty -->\n @if (mobileMenuHasContent()) {\n <rlb-fab\n size=\"sm\"\n outline\n toggle=\"offcanvas\"\n toggle-target=\"mobileMenuOffcanvas\"\n >\n <i class=\"bi bi-three-dots-vertical\"></i>\n </rlb-fab>\n\n <rlb-offcanvas\n #mobileOffcanvas\n id=\"mobileMenuOffcanvas\"\n [placement]=\"'end'\"\n (statusChange)=\"onMobileMenuStatusChange($event)\"\n >\n <rlb-offcanvas-header class=\"border-bottom\">\n <h5\n rlb-offcanvas-title\n class=\"fw-bold mb-0\"\n >\n Menu\n </h5>\n </rlb-offcanvas-header>\n\n <rlb-offcanvas-body class=\"p-0 overflow-x-hidden\">\n <!-- App-provided mobile chrome (RLB_APP_NAVCOMP `mobile` slot) -->\n @for (navComponent of navMobileItems(); track navComponent) {\n <ng-container\n *ngComponentOutlet=\"\n navComponent | mobileComponent;\n injector: mobileSurfaceInjector\n \"\n />\n }\n\n <!-- Mobile Apps Grid -->\n @if (navbarHasApps() && apps().length > 1) {\n <div class=\"border-bottom pb-2\">\n <rlb-app-dropdown-selector\n mode=\"mobile\"\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n </div>\n }\n\n <!-- Mobile Settings Carousel -->\n @if (navbarHasSettings()) {\n <div class=\"pt-2\">\n <rlb-settings-dropdown-selector\n mode=\"mobile\"\n #mobileSettingsMenu\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n </div>\n }\n </rlb-offcanvas-body>\n </rlb-offcanvas>\n }\n } @else {\n <rlb-fab\n size=\"sm\"\n (click)=\"loginNav($event)\"\n [tooltip]=\"'core.account.login' | translate\"\n >\n <i class=\"bi bi-box-arrow-in-left\"></i>\n </rlb-fab>\n }\n </div>\n\n <rlb-navbar-items>\n @for (navComponent of navLeftItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container\n *ngComponentOutlet=\"navComponent | leftComponent; injector: navbarSurfaceInjector\"\n ></ng-container>\n </ng-container>\n }\n </rlb-navbar-items>\n\n <rlb-navbar-items class=\"ms-auto align-items-center\">\n @for (navComponent of navRightItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container\n *ngComponentOutlet=\"navComponent | rightComponent; injector: navbarSurfaceInjector\"\n ></ng-container>\n </ng-container>\n }\n @if (separatorVisible() && isAuthenticated()) {\n <rlb-navbar-separator />\n }\n\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n @if (navbarLayout() == 'default') {\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.account.login' | translate\"\n >\n <i class=\"bi bi-box-arrow-in-left\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.login' | translate }}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasLogin() && isAuthenticated()) {\n <rlb-navbar-item [router-link]=\"'/profile'\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.account.title' | translate\"\n >\n <i class=\"bi bi-person\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.title' | translate }}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasSettings()) {\n <rlb-navbar-item [router-link]=\"'/settings'\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.settings.title' | translate\"\n >\n <i class=\"bi bi-gear\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.settings.title' | translate }}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasApps() && apps().length > 1) {\n <rlb-navbar-item [router-link]=\"'/apps'\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.apps.button' | translate\"\n >\n <i class=\"bi bi-grid-3x3-gap-fill\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.apps.button' | translate }}</span>\n </rlb-navbar-item>\n }\n } @else if (navbarLayout() == 'dropdown') {\n <!-- MODERN DROPDOWN MODE -->\n\n <!--Unauthenticated Login -->\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.account.login' | translate\"\n >\n <i class=\"bi bi-box-arrow-in-left fs-5\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.login' | translate }}</span>\n </rlb-navbar-item>\n }\n\n <!-- Profile & Settings Account Card -->\n @if (navbarHasSettings() && isAuthenticated()) {\n <rlb-settings-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n }\n\n <!-- Apps Launcher -->\n @if (navbarHasApps() && isAuthenticated() && apps().length > 1) {\n <rlb-app-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n }\n }\n </ng-container>\n </rlb-navbar-items>\n </rlb-navbar>\n }\n <div class=\"rlb-main-wrapper\">\n @if (sidebarVisible()) {\n <rlb-sidebar\n [dark]=\"theme() === 'dark'\"\n id=\"sidebar\"\n class=\"rlb-sidebar\"\n >\n @for (item of sidebarItems(); track $index) {\n <rlb-sidebar-item\n *roles=\"item.action\"\n [icon]=\"item.icon\"\n [link]=\"item.url\"\n [title]=\"item.title\"\n [label]=\"item.label\"\n [badgeCounter]=\"item.badgeCounter\"\n (click)=\"onSideBarItemClick(item)\"\n >\n {{ item.label }}\n @for (subitem of item.items || []; track $index) {\n <rlb-sidebar-item\n *roles=\"subitem.action\"\n [icon]=\"subitem.icon\"\n [link]=\"subitem.url\"\n [title]=\"subitem.title\"\n [label]=\"subitem.label\"\n [badgeCounter]=\"subitem.badgeCounter\"\n (click)=\"onSideBarItemClick(subitem)\"\n >\n {{ subitem.label }}\n </rlb-sidebar-item>\n }\n </rlb-sidebar-item>\n }\n @if (sidebarFooter(); as footerName) {\n <div\n rlb-sidebar-footer\n class=\"mt-auto\"\n >\n <ng-container *ngComponentOutlet=\"footerName | sidebarFooterComponent\"></ng-container>\n </div>\n }\n </rlb-sidebar>\n }\n <div class=\"rlb-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!--@if (modalContainerId()) {-->\n<!-- <rlb-modal-container [id]=\"modalContainerId()\" />-->\n<!--}-->\n\n<!--@if (toastContainerIds()) {-->\n<!-- @if (Array.isArray(toastContainerIds())) {-->\n<!-- @for (toastContainerId of toastContainerIds() | asMulti; track toastContainerId) {-->\n<!-- <rlb-toast-container [id]=\"toastContainerId\" />-->\n<!-- }-->\n<!-- } @else {-->\n<!-- <rlb-toast-container class=\"position-fixed bottom-0 end-0 p-3\" [id]=\"toastContainerIds() | asSingle\" />-->\n<!-- }-->\n<!--}-->\n", styles: [".separator{border-left:1px solid;padding:0 2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$6.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: NavbarComponent, selector: "rlb-navbar", inputs: ["dark", "showSideBarToggler", "color", "placement", "expand", "class", "enable-dropdown-toggler"] }, { kind: "directive", type: NavbarBrandDirective, selector: "[rlb-navbar-brand]" }, { kind: "component", type: NavbarFormComponent, selector: "rlb-navbar-form", inputs: ["role", "class"] }, { kind: "component", type: NavbarItemsComponent, selector: "rlb-navbar-items", inputs: ["scroll", "class"], outputs: ["click"] }, { kind: "component", type: NavbarItemComponent, selector: "rlb-navbar-item", inputs: ["disabled", "router-link", "class"], outputs: ["click"] }, { kind: "component", type: NavbarSeparatorComponent, selector: "rlb-navbar-separator", inputs: ["class"] }, { kind: "component", type: SidebarComponent, selector: "rlb-sidebar", inputs: ["dark", "rounded"] }, { kind: "component", type: SidebarItemComponent, selector: "rlb-sidebar-item", inputs: ["title", "icon", "label", "link", "badgeCounter"], outputs: ["click"] }, { kind: "component", type: OffcanvasComponent, selector: "rlb-offcanvas", inputs: ["id", "body-scroll", "scroll-backup", "close-manual", "placement", "responsive"], outputs: ["statusChange"] }, { kind: "component", type: OffcanvasHeaderComponent, selector: "rlb-offcanvas-header", inputs: ["offcanvasId"] }, { kind: "component", type: OffcanvasBodyComponent, selector: "rlb-offcanvas-body" }, { kind: "component", type: RlbFabComponent, selector: "rlb-fab", inputs: ["color", "size", "disabled", "outline", "position"] }, { kind: "component", type: InputGroupComponent, selector: "rlb-input-group", inputs: ["text", "validate", "size"] }, { kind: "component", type: InputComponent, selector: "rlb-input", inputs: ["disabled", "readonly", "placeholder", "type", "size", "name", "max", "min", "step", "date-type", "timezone", "inputId", "extValidation", "enable-validation"] }, { kind: "directive", type: TooltipDirective, selector: "[tooltip]", inputs: ["tooltip", "tooltip-placement", "tooltip-class", "tooltip-html"] }, { kind: "directive", type: RlbRole, selector: "[roles]", inputs: ["roles"] }, { kind: "component", type: AppDropdownSelectorComponent, selector: "rlb-app-dropdown-selector", inputs: ["mode", "apps", "isAuthenticated"], outputs: ["appSelected"] }, { kind: "component", type: SettingsDropdownSelectorComponent, selector: "rlb-settings-dropdown-selector", inputs: ["mode", "apps", "isAuthenticated"], outputs: ["appSelected"] }, { kind: "component", type: ButtonComponent, selector: "button[rlb-button], a[rlb-button]", inputs: ["color", "size", "disabled", "outline", "isLink"] }, { kind: "directive", type: ToggleDirective, selector: " button[toggle], a[toggle], rlb-navbar-item[toggle], rlb-button-toolbar[toggle], rlb-fab[toggle],", inputs: ["toggle", "toggle-target", "collapsed", "auto-close"] }, { kind: "pipe", type: i1$4.TranslatePipe, name: "translate" }, { kind: "pipe", type: LeftComponentPipe, name: "leftComponent" }, { kind: "pipe", type: MobileComponentPipe, name: "mobileComponent" }, { kind: "pipe", type: RightComponentPipe, name: "rightComponent" }, { kind: "pipe", type: SidebarFooterComponentPipe, name: "sidebarFooterComponent" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2451
2492
  }
2452
2493
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: AppTemplateComponent, decorators: [{
2453
2494
  type: Component,
@@ -2473,6 +2514,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
2473
2514
  InputComponent,
2474
2515
  TooltipDirective,
2475
2516
  LeftComponentPipe,
2517
+ MobileComponentPipe,
2476
2518
  RightComponentPipe,
2477
2519
  SidebarFooterComponentPipe,
2478
2520
  RlbRole,
@@ -2480,7 +2522,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
2480
2522
  SettingsDropdownSelectorComponent,
2481
2523
  ButtonComponent,
2482
2524
  ToggleDirective,
2483
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"rlb-app\">\n @if (navVisible()) {\n <rlb-navbar [dark]=\"theme() === 'dark'\" [showSideBarToggler]=\"sidebarVisible()\" expand=\"lg\" class=\"border-bottom py-1 rlb-navbar\">\n @if (navHeader(); as header) {\n <a rlb-navbar-brand href=\"#\">\n\n @if (header.type === 'text') {\n {{ header.text }}\n }\n\n @if (header.type === 'image') {\n <img\n [src]=\"header.src\"\n [alt]=\"header.alt ?? 'Brand'\"\n [height]=\"header.height ?? 40\"\n />\n }\n </a>\n }\n @if (navSearchVisible()) {\n <rlb-navbar-form>\n <rlb-input-group class=\"my-1 mx-3\" validate>\n <rlb-input type=\"search\" class=\"search-input\" placeholder=\"Search\" [(ngModel)]=\"navSearchText\"\n (keyup.enter)=\"setNavbarSearchText(navSearchText)\" name=\"search\" size=\"small\">\n <button after rlb-button outline type=\"submit\" (click)=\"setNavbarSearchText(navSearchText)\" size=\"sm\">\n <i class=\"bi bi-search\"></i>\n </button>\n </rlb-input>\n </rlb-input-group>\n </rlb-navbar-form>\n }\n\n <!-- MOBILE VIEWS -->\n <div rlb-custom-navbar-items class=\"d-flex d-lg-none\">\n @if (isAuthenticated()) {\n <rlb-fab size=\"sm\" outline toggle=\"offcanvas\" toggle-target=\"mobileMenuOffcanvas\">\n <i class=\"bi bi-three-dots-vertical\"></i>\n </rlb-fab>\n\n <rlb-offcanvas\n #mobileOffcanvas\n id=\"mobileMenuOffcanvas\"\n [placement]=\"'end'\"\n (statusChange)=\"onMobileMenuStatusChange($event)\"\n >\n <rlb-offcanvas-header class=\"border-bottom\">\n <h5 rlb-offcanvas-title class=\"fw-bold mb-0\">Menu</h5>\n </rlb-offcanvas-header>\n\n <rlb-offcanvas-body class=\"p-0 overflow-x-hidden\">\n\n <!-- Mobile Apps Grid -->\n @if (navbarHasApps() && apps().length > 1) {\n <div class=\"border-bottom pb-2\">\n <rlb-app-dropdown-selector\n mode=\"mobile\"\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n </div>\n }\n\n <!-- Mobile Settings Carousel -->\n @if (isAuthenticated() || navbarHasSettings()) {\n <div class=\"pt-2\">\n <rlb-settings-dropdown-selector\n mode=\"mobile\"\n #mobileSettingsMenu\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n </div>\n }\n\n </rlb-offcanvas-body>\n </rlb-offcanvas>\n } @else {\n <rlb-fab size=\"sm\" (click)=\"loginNav($event)\" [tooltip]=\"('core.account.login') |translate\">\n <i class=\" bi bi-box-arrow-in-left\"></i>\n </rlb-fab>\n }\n\n </div>\n\n <rlb-navbar-items>\n @for (navComponent of navLeftItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container *ngComponentOutlet=\"navComponent | leftComponent\"></ng-container>\n </ng-container>\n }\n </rlb-navbar-items>\n\n <rlb-navbar-items class=\"ms-auto align-items-center\">\n @for (navComponent of navRightItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container *ngComponentOutlet=\"navComponent | rightComponent\"></ng-container>\n </ng-container>\n }\n @if (separatorVisible() && isAuthenticated()) {\n <rlb-navbar-separator />\n }\n\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n @if (navbarLayout() == 'default') {\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.account.login') |translate\">\n <i class=\" bi bi-box-arrow-in-left\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.account.login' | translate}}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasLogin() && isAuthenticated()) {\n <rlb-navbar-item [router-link]=\"'/profile'\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.account.title') |translate\">\n <i class=\"bi bi-person\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.account.title' | translate}}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasSettings()) {\n <rlb-navbar-item [router-link]=\"'/settings'\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.settings.title') |translate\">\n <i class=\"bi bi-gear\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.settings.title' | translate}}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasApps() && apps().length > 1) {\n <rlb-navbar-item [router-link]=\"'/apps'\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.apps.button') |translate\">\n <i class=\"bi bi-grid-3x3-gap-fill\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{'core.apps.button' | translate}}</span>\n </rlb-navbar-item>\n }\n\n } @else if (navbarLayout() == 'dropdown') {\n <!-- MODERN DROPDOWN MODE -->\n\n <!--Unauthenticated Login -->\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span tooltip-placement=\"bottom\" [tooltip]=\"('core.account.login') | translate\">\n <i class=\"bi bi-box-arrow-in-left fs-5\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.login' | translate }}</span>\n </rlb-navbar-item>\n }\n\n <!-- Profile & Settings Account Card -->\n @if (navbarHasSettings() && isAuthenticated()) {\n <rlb-settings-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n }\n\n <!-- Apps Launcher -->\n @if (navbarHasApps() && isAuthenticated() && apps().length > 1) {\n <rlb-app-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n }\n }\n </ng-container>\n </rlb-navbar-items>\n </rlb-navbar>\n }\n <div class=\"rlb-main-wrapper\">\n @if (sidebarVisible()) {\n <rlb-sidebar [dark]=\"theme() === 'dark'\" id=\"sidebar\" class=\"rlb-sidebar\">\n @for (item of sidebarItems(); track $index) {\n <rlb-sidebar-item\n *roles=\"item.action\"\n [icon]=\"item.icon\" [link]=\"item.url\"\n [title]=\"item.title\" [label]=\"item.label\"\n [badgeCounter]=\"item.badgeCounter\"\n (click)=\"onSideBarItemClick(item)\"\n >\n {{item.label}}\n @for (subitem of item.items || []; track $index) {\n <rlb-sidebar-item\n *roles=\"subitem.action\"\n [icon]=\"subitem.icon\"\n [link]=\"subitem.url\"\n [title]=\"subitem.title\"\n [label]=\"subitem.label\"\n [badgeCounter]=\"subitem.badgeCounter\"\n (click)=\"onSideBarItemClick(subitem)\"\n >\n {{subitem.label}}\n </rlb-sidebar-item>\n }\n </rlb-sidebar-item>\n }\n @if (sidebarFooter(); as footerName) {\n <div rlb-sidebar-footer class=\"mt-auto\">\n <ng-container *ngComponentOutlet=\"footerName | sidebarFooterComponent\"></ng-container>\n </div>\n }\n </rlb-sidebar>\n }\n <div class=\"rlb-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!--@if (modalContainerId()) {-->\n<!-- <rlb-modal-container [id]=\"modalContainerId()\" />-->\n<!--}-->\n\n<!--@if (toastContainerIds()) {-->\n<!-- @if (Array.isArray(toastContainerIds())) {-->\n<!-- @for (toastContainerId of toastContainerIds() | asMulti; track toastContainerId) {-->\n<!-- <rlb-toast-container [id]=\"toastContainerId\" />-->\n<!-- }-->\n<!-- } @else {-->\n<!-- <rlb-toast-container class=\"position-fixed bottom-0 end-0 p-3\" [id]=\"toastContainerIds() | asSingle\" />-->\n<!-- }-->\n<!--}-->\n", styles: [".separator{border-left:1px solid;padding:0 2px}\n"] }]
2525
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"rlb-app\">\n @if (navVisible()) {\n <rlb-navbar\n [dark]=\"theme() === 'dark'\"\n [showSideBarToggler]=\"sidebarVisible()\"\n expand=\"lg\"\n class=\"border-bottom py-1 rlb-navbar\"\n >\n @if (navHeader(); as header) {\n <a\n rlb-navbar-brand\n href=\"#\"\n >\n @if (header.type === 'text') {\n {{ header.text }}\n }\n\n @if (header.type === 'image') {\n <img\n [src]=\"header.src\"\n [alt]=\"header.alt ?? 'Brand'\"\n [height]=\"header.height ?? 40\"\n />\n }\n </a>\n }\n @if (navSearchVisible()) {\n <rlb-navbar-form>\n <rlb-input-group\n class=\"my-1 mx-3\"\n validate\n >\n <rlb-input\n type=\"search\"\n class=\"search-input\"\n placeholder=\"Search\"\n [(ngModel)]=\"navSearchText\"\n (keyup.enter)=\"setNavbarSearchText(navSearchText)\"\n name=\"search\"\n size=\"small\"\n >\n <button\n after\n rlb-button\n outline\n type=\"submit\"\n (click)=\"setNavbarSearchText(navSearchText)\"\n size=\"sm\"\n >\n <i class=\"bi bi-search\"></i>\n </button>\n </rlb-input>\n </rlb-input-group>\n </rlb-navbar-form>\n }\n\n <!-- MOBILE VIEWS -->\n <div\n rlb-custom-navbar-items\n class=\"d-flex d-lg-none\"\n >\n @if (isAuthenticated()) {\n <!-- No toggler when the panel would render empty -->\n @if (mobileMenuHasContent()) {\n <rlb-fab\n size=\"sm\"\n outline\n toggle=\"offcanvas\"\n toggle-target=\"mobileMenuOffcanvas\"\n >\n <i class=\"bi bi-three-dots-vertical\"></i>\n </rlb-fab>\n\n <rlb-offcanvas\n #mobileOffcanvas\n id=\"mobileMenuOffcanvas\"\n [placement]=\"'end'\"\n (statusChange)=\"onMobileMenuStatusChange($event)\"\n >\n <rlb-offcanvas-header class=\"border-bottom\">\n <h5\n rlb-offcanvas-title\n class=\"fw-bold mb-0\"\n >\n Menu\n </h5>\n </rlb-offcanvas-header>\n\n <rlb-offcanvas-body class=\"p-0 overflow-x-hidden\">\n <!-- App-provided mobile chrome (RLB_APP_NAVCOMP `mobile` slot) -->\n @for (navComponent of navMobileItems(); track navComponent) {\n <ng-container\n *ngComponentOutlet=\"\n navComponent | mobileComponent;\n injector: mobileSurfaceInjector\n \"\n />\n }\n\n <!-- Mobile Apps Grid -->\n @if (navbarHasApps() && apps().length > 1) {\n <div class=\"border-bottom pb-2\">\n <rlb-app-dropdown-selector\n mode=\"mobile\"\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n </div>\n }\n\n <!-- Mobile Settings Carousel -->\n @if (navbarHasSettings()) {\n <div class=\"pt-2\">\n <rlb-settings-dropdown-selector\n mode=\"mobile\"\n #mobileSettingsMenu\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n </div>\n }\n </rlb-offcanvas-body>\n </rlb-offcanvas>\n }\n } @else {\n <rlb-fab\n size=\"sm\"\n (click)=\"loginNav($event)\"\n [tooltip]=\"'core.account.login' | translate\"\n >\n <i class=\"bi bi-box-arrow-in-left\"></i>\n </rlb-fab>\n }\n </div>\n\n <rlb-navbar-items>\n @for (navComponent of navLeftItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container\n *ngComponentOutlet=\"navComponent | leftComponent; injector: navbarSurfaceInjector\"\n ></ng-container>\n </ng-container>\n }\n </rlb-navbar-items>\n\n <rlb-navbar-items class=\"ms-auto align-items-center\">\n @for (navComponent of navRightItems(); track navComponent) {\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n <ng-container\n *ngComponentOutlet=\"navComponent | rightComponent; injector: navbarSurfaceInjector\"\n ></ng-container>\n </ng-container>\n }\n @if (separatorVisible() && isAuthenticated()) {\n <rlb-navbar-separator />\n }\n\n <ng-container ngProjectAs=\"rlb-navbar-item\">\n @if (navbarLayout() == 'default') {\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.account.login' | translate\"\n >\n <i class=\"bi bi-box-arrow-in-left\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.login' | translate }}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasLogin() && isAuthenticated()) {\n <rlb-navbar-item [router-link]=\"'/profile'\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.account.title' | translate\"\n >\n <i class=\"bi bi-person\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.title' | translate }}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasSettings()) {\n <rlb-navbar-item [router-link]=\"'/settings'\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.settings.title' | translate\"\n >\n <i class=\"bi bi-gear\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.settings.title' | translate }}</span>\n </rlb-navbar-item>\n }\n\n @if (navbarHasApps() && apps().length > 1) {\n <rlb-navbar-item [router-link]=\"'/apps'\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.apps.button' | translate\"\n >\n <i class=\"bi bi-grid-3x3-gap-fill\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.apps.button' | translate }}</span>\n </rlb-navbar-item>\n }\n } @else if (navbarLayout() == 'dropdown') {\n <!-- MODERN DROPDOWN MODE -->\n\n <!--Unauthenticated Login -->\n @if (navbarHasLogin() && !isAuthenticated()) {\n <rlb-navbar-item (click)=\"loginNav($event)\">\n <span\n tooltip-placement=\"bottom\"\n [tooltip]=\"'core.account.login' | translate\"\n >\n <i class=\"bi bi-box-arrow-in-left fs-5\"></i>\n </span>\n <span class=\"ms-1 d-lg-none\">{{ 'core.account.login' | translate }}</span>\n </rlb-navbar-item>\n }\n\n <!-- Profile & Settings Account Card -->\n @if (navbarHasSettings() && isAuthenticated()) {\n <rlb-settings-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'settings')\"\n />\n }\n\n <!-- Apps Launcher -->\n @if (navbarHasApps() && isAuthenticated() && apps().length > 1) {\n <rlb-app-dropdown-selector\n [apps]=\"apps()\"\n [isAuthenticated]=\"isAuthenticated()\"\n (appSelected)=\"selectApp($event, 'app')\"\n />\n }\n }\n </ng-container>\n </rlb-navbar-items>\n </rlb-navbar>\n }\n <div class=\"rlb-main-wrapper\">\n @if (sidebarVisible()) {\n <rlb-sidebar\n [dark]=\"theme() === 'dark'\"\n id=\"sidebar\"\n class=\"rlb-sidebar\"\n >\n @for (item of sidebarItems(); track $index) {\n <rlb-sidebar-item\n *roles=\"item.action\"\n [icon]=\"item.icon\"\n [link]=\"item.url\"\n [title]=\"item.title\"\n [label]=\"item.label\"\n [badgeCounter]=\"item.badgeCounter\"\n (click)=\"onSideBarItemClick(item)\"\n >\n {{ item.label }}\n @for (subitem of item.items || []; track $index) {\n <rlb-sidebar-item\n *roles=\"subitem.action\"\n [icon]=\"subitem.icon\"\n [link]=\"subitem.url\"\n [title]=\"subitem.title\"\n [label]=\"subitem.label\"\n [badgeCounter]=\"subitem.badgeCounter\"\n (click)=\"onSideBarItemClick(subitem)\"\n >\n {{ subitem.label }}\n </rlb-sidebar-item>\n }\n </rlb-sidebar-item>\n }\n @if (sidebarFooter(); as footerName) {\n <div\n rlb-sidebar-footer\n class=\"mt-auto\"\n >\n <ng-container *ngComponentOutlet=\"footerName | sidebarFooterComponent\"></ng-container>\n </div>\n }\n </rlb-sidebar>\n }\n <div class=\"rlb-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!--@if (modalContainerId()) {-->\n<!-- <rlb-modal-container [id]=\"modalContainerId()\" />-->\n<!--}-->\n\n<!--@if (toastContainerIds()) {-->\n<!-- @if (Array.isArray(toastContainerIds())) {-->\n<!-- @for (toastContainerId of toastContainerIds() | asMulti; track toastContainerId) {-->\n<!-- <rlb-toast-container [id]=\"toastContainerId\" />-->\n<!-- }-->\n<!-- } @else {-->\n<!-- <rlb-toast-container class=\"position-fixed bottom-0 end-0 p-3\" [id]=\"toastContainerIds() | asSingle\" />-->\n<!-- }-->\n<!--}-->\n", styles: [".separator{border-left:1px solid;padding:0 2px}\n"] }]
2484
2526
  }], ctorParameters: () => [], propDecorators: { modalContainerId: [{ type: i0.Input, args: [{ isSignal: true, alias: "modal-container-id", required: true }] }], breadcrumbInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumb", required: false }] }], toastContainerIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "toast-container-ids", required: true }] }], mobileOffcanvas: [{ type: i0.ViewChild, args: ['mobileOffcanvas', { isSignal: true }] }], mobileSettingsMenu: [{ type: i0.ViewChild, args: ['mobileSettingsMenu', { isSignal: true }] }] } });
2485
2527
 
2486
2528
  class BaseComponent {
@@ -2690,6 +2732,7 @@ class RlbAppModule {
2690
2732
  AsMultiPipe,
2691
2733
  AsSinglePipe,
2692
2734
  LeftComponentPipe,
2735
+ MobileComponentPipe,
2693
2736
  RightComponentPipe,
2694
2737
  TruncatePipe,
2695
2738
  AutolinkPipe,
@@ -2706,6 +2749,7 @@ class RlbAppModule {
2706
2749
  AsMultiPipe,
2707
2750
  AsSinglePipe,
2708
2751
  LeftComponentPipe,
2752
+ MobileComponentPipe,
2709
2753
  RightComponentPipe,
2710
2754
  TruncatePipe,
2711
2755
  AutolinkPipe,
@@ -2758,6 +2802,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
2758
2802
  AsMultiPipe,
2759
2803
  AsSinglePipe,
2760
2804
  LeftComponentPipe,
2805
+ MobileComponentPipe,
2761
2806
  RightComponentPipe,
2762
2807
  TruncatePipe,
2763
2808
  AutolinkPipe,
@@ -2794,6 +2839,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
2794
2839
  AsMultiPipe,
2795
2840
  AsSinglePipe,
2796
2841
  LeftComponentPipe,
2842
+ MobileComponentPipe,
2797
2843
  RightComponentPipe,
2798
2844
  TruncatePipe,
2799
2845
  AutolinkPipe,
@@ -3469,7 +3515,7 @@ const navbarsFeature = createFeature({
3469
3515
  reducer: createReducer(initialNavbarState, on(NavbarActions.setVisible, (state, { visible }) => ({ ...state, visible })), on(NavbarActions.setSearchVisible, (state, { visible }) => ({
3470
3516
  ...state,
3471
3517
  searchVisible: visible,
3472
- })), on(NavbarActions.setHeader, (state, { header }) => ({ ...state, header })), on(NavbarActions.setSearchText, (state, { text }) => ({ ...state, searchText: text })), on(NavbarActions.setLeftItems, (state, { items }) => ({ ...state, leftItems: items })), on(NavbarActions.setRightItems, (state, { items }) => ({ ...state, rightItems: items })), on(NavbarActions.setLoginVisible, (state, { visible }) => ({
3518
+ })), on(NavbarActions.setHeader, (state, { header }) => ({ ...state, header })), on(NavbarActions.setSearchText, (state, { text }) => ({ ...state, searchText: text })), on(NavbarActions.setLeftItems, (state, { items }) => ({ ...state, leftItems: items })), on(NavbarActions.setRightItems, (state, { items }) => ({ ...state, rightItems: items })), on(NavbarActions.setMobileItems, (state, { items }) => ({ ...state, mobileItems: items })), on(NavbarActions.setLoginVisible, (state, { visible }) => ({
3473
3519
  ...state,
3474
3520
  loginVisible: visible,
3475
3521
  })), on(NavbarActions.setSettingsVisible, (state, { visible }) => ({
@@ -3667,5 +3713,5 @@ function flattenRoutes(routes, parentPath = '') {
3667
3713
  * Generated bundle index. Do not edit.
3668
3714
  */
3669
3715
 
3670
- export { AbstractMdService, AbstractSupportService, AclStore, AppBreadcrumbService, AppContainerComponent, AppContextActions, AppContextActionsInternal, AppLoggerService, AppStorageService, AppTemplateComponent, AppsService, AsMultiPipe, AsSinglePipe, AuthActions, AuthActionsInternal, AuthFeatureService, AuthenticationService, AutolinkPipe, BaseComponent, CmsComponent, CmsPipe, ContentComponent, CookiesService, ErrorManagementService, ErrorModalComponent, KeycloakProfileService, LanguageService, LeftComponentPipe, LocalCacheService, ModalAppsComponent, NavbarActions, NavbarActionsInternal, OauthPasswordService, ParseJwtService, PwaUpdaterService, RLB_APPS, RLB_APP_NAVCOMP, RLB_APP_SIDEBARCOMP, RLB_AUTH_URL_HANDLER, RLB_CFG, RLB_CFG_ACL, RLB_CFG_AUTH, RLB_CFG_CMS, RLB_CFG_ENV, RLB_CFG_I18N, RLB_CFG_PAGES, RLB_INIT_PROVIDER, RightComponentPipe, RlbAppModule, RlbRole, SidebarActions, SidebarActionsInternal, SidebarFooterComponentPipe, StrapiService, ToastComponent, TokenOauthInterceptor, TranslateBrowserLoader, TruncatePipe, UtilsService, aclFeatureKey, appContextFeatureKey, authsFeatureKey, getDefaultRoutes, initialAclState, initialAppContextState, initialAuthState, initialNavbarState, initialSidebarState, navbarsFeatureKey, oauthGuard, oauthPasswordGuard, permissionGuard, provideApp, provideRlbCodeBrowserOAuth, provideRlbConfig, provideRlbI18n, sidebarsFeatureKey, translateBrowserLoaderFactory, verifyDeactivate };
3716
+ export { AbstractMdService, AbstractSupportService, AclStore, AppBreadcrumbService, AppContainerComponent, AppContextActions, AppContextActionsInternal, AppLoggerService, AppStorageService, AppTemplateComponent, AppsService, AsMultiPipe, AsSinglePipe, AuthActions, AuthActionsInternal, AuthFeatureService, AuthenticationService, AutolinkPipe, BaseComponent, CmsComponent, CmsPipe, ContentComponent, CookiesService, ErrorManagementService, ErrorModalComponent, KeycloakProfileService, LanguageService, LeftComponentPipe, LocalCacheService, MobileComponentPipe, ModalAppsComponent, NavbarActions, NavbarActionsInternal, OauthPasswordService, ParseJwtService, PwaUpdaterService, RLB_APPS, RLB_APP_NAVCOMP, RLB_APP_SIDEBARCOMP, RLB_AUTH_URL_HANDLER, RLB_CFG, RLB_CFG_ACL, RLB_CFG_AUTH, RLB_CFG_CMS, RLB_CFG_ENV, RLB_CFG_I18N, RLB_CFG_PAGES, RLB_INIT_PROVIDER, RLB_NAV_SURFACE, RightComponentPipe, RlbAppModule, RlbRole, SidebarActions, SidebarActionsInternal, SidebarFooterComponentPipe, StrapiService, ToastComponent, TokenOauthInterceptor, TranslateBrowserLoader, TruncatePipe, UtilsService, aclFeatureKey, appContextFeatureKey, authsFeatureKey, getDefaultRoutes, initialAclState, initialAppContextState, initialAuthState, initialNavbarState, initialSidebarState, navbarsFeatureKey, oauthGuard, oauthPasswordGuard, permissionGuard, provideApp, provideRlbCodeBrowserOAuth, provideRlbConfig, provideRlbI18n, sidebarsFeatureKey, translateBrowserLoaderFactory, verifyDeactivate };
3671
3717
  //# sourceMappingURL=open-rlb-ng-app.mjs.map