@flusys/ng-layout 5.2.0 → 5.3.0

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.
@@ -83,8 +83,8 @@
83
83
  }
84
84
 
85
85
  .layout-topbar-action-right {
86
- margin-left: auto !important;
87
- margin-right: -0.9rem !important;
86
+ margin-inline-start: auto !important;
87
+ margin-inline-end: -0.9rem !important;
88
88
  }
89
89
 
90
90
  .layout-menu-button {
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, PLATFORM_ID, Injectable, DOCUMENT, signal, computed, effect, Component, afterNextRender, InjectionToken, input, DestroyRef, viewChild, ElementRef, Renderer2 } from '@angular/core';
2
+ import { inject, PLATFORM_ID, Injectable, DOCUMENT, signal, computed, effect, Component, InjectionToken, input, DestroyRef, viewChild, ElementRef, Renderer2 } from '@angular/core';
3
3
  import * as i2$3 from '@flusys/ng-shared';
4
4
  import { evaluateLogicNode, PermissionValidatorService, InlineSvgComponent, TranslatePipe, TranslateService, IconComponent, AngularModule, PrimeModule } from '@flusys/ng-shared';
5
5
  import { isPlatformBrowser, NgComponentOutlet, DOCUMENT as DOCUMENT$1, NgClass } from '@angular/common';
@@ -9,7 +9,7 @@ import * as i1 from '@angular/forms';
9
9
  import { FormsModule } from '@angular/forms';
10
10
  import * as i1$2 from '@angular/router';
11
11
  import { Router, NavigationEnd, RouterModule } from '@angular/router';
12
- import { updatePreset, updateSurfacePalette, $t, definePreset } from '@primeuix/themes';
12
+ import { definePreset, updatePreset, updateSurfacePalette, $t } from '@primeuix/themes';
13
13
  import Aura from '@primeuix/themes/aura';
14
14
  import Lara from '@primeuix/themes/lara';
15
15
  import Nora from '@primeuix/themes/nora';
@@ -92,36 +92,11 @@ function filterMenuItem(item, permissionCode) {
92
92
 
93
93
  const STORAGE_KEY = 'flusys.layout.config';
94
94
  const STORAGE_VERSION = 1;
95
- /**
96
- * Service for persisting layout configuration to localStorage.
97
- * Handles loading, saving, and validation of layout preferences with SSR-safe checks.
98
- *
99
- * @example
100
- * ```typescript
101
- * const persistence = inject(LayoutPersistenceService);
102
- *
103
- * // Load saved config
104
- * const config = persistence.load();
105
- *
106
- * // Save config
107
- * persistence.save({ darkTheme: true, preset: 'Aura' });
108
- *
109
- * // Clear saved config
110
- * persistence.clear();
111
- * ```
112
- */
113
95
  class LayoutPersistenceService {
114
96
  platformId = inject(PLATFORM_ID);
115
97
  isBrowser = isPlatformBrowser(this.platformId);
116
98
  validPresets = ['Aura', 'Lara', 'Nora'];
117
99
  validMenuModes = ['static', 'overlay', 'topbar'];
118
- /**
119
- * Load configuration from localStorage.
120
- * Returns null if no saved config or invalid data.
121
- * SSR-safe (returns null on server).
122
- *
123
- * @returns Validated layout configuration or null
124
- */
125
100
  load() {
126
101
  if (!this.isBrowser)
127
102
  return null;
@@ -137,12 +112,6 @@ class LayoutPersistenceService {
137
112
  return null;
138
113
  }
139
114
  }
140
- /**
141
- * Save configuration to localStorage.
142
- * SSR-safe (no-op on server).
143
- *
144
- * @param config Layout configuration to save
145
- */
146
115
  save(config) {
147
116
  if (!this.isBrowser)
148
117
  return;
@@ -157,41 +126,25 @@ class LayoutPersistenceService {
157
126
  // Silent fail - localStorage may be full or disabled
158
127
  }
159
128
  }
160
- /**
161
- * Clear stored configuration.
162
- * SSR-safe (no-op on server).
163
- */
164
129
  clear() {
165
130
  if (!this.isBrowser)
166
131
  return;
167
132
  localStorage.removeItem(STORAGE_KEY);
168
133
  }
169
- /**
170
- * Validate and sanitize configuration.
171
- * Returns null if version mismatch.
172
- *
173
- * @param config Configuration to validate
174
- * @returns Validated configuration or null
175
- */
176
134
  validateConfig(config) {
177
- // Version mismatch - clear and return null
178
135
  if (config._version && config._version !== STORAGE_VERSION) {
179
136
  this.clear();
180
137
  return null;
181
138
  }
182
- // Validate preset - silently fix invalid values
183
139
  if (config.preset && !this.validPresets.includes(config.preset)) {
184
140
  config.preset = 'Aura';
185
141
  }
186
- // Validate menuMode - silently fix invalid values
187
142
  if (config.menuMode && !this.validMenuModes.includes(config.menuMode)) {
188
143
  config.menuMode = 'static';
189
144
  }
190
- // Validate darkTheme
191
145
  if (typeof config.darkTheme !== 'boolean') {
192
146
  config.darkTheme = false;
193
147
  }
194
- // Remove version field from returned config
195
148
  const { _version, ...cleanConfig } = config;
196
149
  return cleanConfig;
197
150
  }
@@ -200,21 +153,18 @@ class LayoutPersistenceService {
200
153
  }
201
154
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: LayoutPersistenceService, decorators: [{
202
155
  type: Injectable,
203
- args: [{
204
- providedIn: 'root',
205
- }]
156
+ args: [{ providedIn: 'root' }]
206
157
  }] });
207
158
 
208
- /** Layout configuration and state management service */
209
159
  class LayoutService {
210
160
  document = inject(DOCUMENT);
211
161
  platformId = inject(PLATFORM_ID);
212
162
  isBrowser = isPlatformBrowser(this.platformId);
213
163
  persistence = inject(LayoutPersistenceService);
214
164
  appConfig = inject(APP_CONFIG, { optional: true });
215
- DEFAULT_CONFIG = {
165
+ DEFAULT_CONFIG = this.appConfig?.layoutConfig ?? {
216
166
  preset: 'Aura',
217
- primary: 'emerald',
167
+ primary: 'violet',
218
168
  surface: null,
219
169
  darkTheme: false,
220
170
  menuMode: 'static',
@@ -227,9 +177,10 @@ class LayoutService {
227
177
  menuHoverActive: false,
228
178
  topbarMenuVisible: true,
229
179
  };
180
+ memorable = this.DEFAULT_CONFIG.isMemorable !== false;
230
181
  _layoutConfig = signal({
231
182
  ...this.DEFAULT_CONFIG,
232
- ...this.persistence.load(),
183
+ ...(this.memorable ? this.persistence.load() : null),
233
184
  }, ...(ngDevMode ? [{ debugName: "_layoutConfig" }] : []));
234
185
  _layoutState = signal(this.DEFAULT_STATE, ...(ngDevMode ? [{ debugName: "_layoutState" }] : []));
235
186
  _transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "_transitionComplete" }] : []));
@@ -243,25 +194,19 @@ class LayoutService {
243
194
  permissionValidator = inject(PermissionValidatorService);
244
195
  userProfile = this._userProfile.asReadonly();
245
196
  companyProfile = this._companyProfile.asReadonly();
246
- // Static app info from config
247
197
  appName = this.appConfig?.appName ?? DEFAULT_APP_NAME;
248
198
  appLogo = this.appConfig?.appLogo ?? '';
249
199
  isAppLogoSvg = this.appLogo.toLowerCase().endsWith('.svg');
250
200
  authorName = this.appConfig?.author?.name ?? DEFAULT_AUTHOR.name;
251
201
  authorUrl = this.appConfig?.author?.url ?? DEFAULT_AUTHOR.url;
252
- // Permission-filtered menu and apps
253
202
  menu = computed(() => filterMenuByPermissions(this._rawMenu(), this.permissionValidator.permissions()), ...(ngDevMode ? [{ debugName: "menu" }] : []));
254
203
  apps = computed(() => filterAppsByPermissions(this._rawApps(), this.permissionValidator.permissions()), ...(ngDevMode ? [{ debugName: "apps" }] : []));
255
204
  hasApps = computed(() => this.apps().length > 0, ...(ngDevMode ? [{ debugName: "hasApps" }] : []));
256
- // Computed signals - Layout
257
205
  isSidebarActive = computed(() => this._layoutState().overlayMenuActive ||
258
206
  this._layoutState().staticMenuMobileActive, ...(ngDevMode ? [{ debugName: "isSidebarActive" }] : []));
259
207
  isDarkTheme = computed(() => this._layoutConfig().darkTheme, ...(ngDevMode ? [{ debugName: "isDarkTheme" }] : []));
260
- getPrimary = computed(() => this._layoutConfig().primary, ...(ngDevMode ? [{ debugName: "getPrimary" }] : []));
261
- getSurface = computed(() => this._layoutConfig().surface, ...(ngDevMode ? [{ debugName: "getSurface" }] : []));
262
208
  isOverlay = computed(() => this._layoutConfig().menuMode === 'overlay', ...(ngDevMode ? [{ debugName: "isOverlay" }] : []));
263
209
  isTopbar = computed(() => this._layoutConfig().menuMode === 'topbar', ...(ngDevMode ? [{ debugName: "isTopbar" }] : []));
264
- // User profile computed signals
265
210
  userName = computed(() => this._userProfile()?.name ?? 'Guest', ...(ngDevMode ? [{ debugName: "userName" }] : []));
266
211
  userEmail = computed(() => this._userProfile()?.email ?? '', ...(ngDevMode ? [{ debugName: "userEmail" }] : []));
267
212
  userProfilePictureUrl = computed(() => this._userProfile()?.profilePictureUrl ?? null, ...(ngDevMode ? [{ debugName: "userProfilePictureUrl" }] : []));
@@ -274,23 +219,20 @@ class LayoutService {
274
219
  }, ...(ngDevMode ? [{ debugName: "companyName" }] : []));
275
220
  displayLogo = computed(() => this.companyLogoUrl() ?? this.appLogo, ...(ngDevMode ? [{ debugName: "displayLogo" }] : []));
276
221
  isDisplayLogoSvg = computed(() => this.displayLogo().toLowerCase().endsWith('.svg'), ...(ngDevMode ? [{ debugName: "isDisplayLogoSvg" }] : []));
277
- // RxJS Subjects for event communication
278
- configUpdate = new Subject();
279
222
  overlayOpen = new Subject();
280
223
  menuSource = new Subject();
281
224
  resetSource = new Subject();
282
225
  menuSource$ = this.menuSource.asObservable();
283
226
  resetSource$ = this.resetSource.asObservable();
284
- configUpdate$ = this.configUpdate.asObservable();
285
227
  overlayOpen$ = this.overlayOpen.asObservable();
286
228
  initialized = false;
287
229
  constructor() {
288
230
  effect(() => {
289
231
  const config = this._layoutConfig();
290
- this.configUpdate.next(config);
291
232
  if (this.initialized) {
292
233
  this.handleDarkModeTransition(config);
293
- this.persistence.save(config);
234
+ if (this.memorable)
235
+ this.persistence.save(config);
294
236
  }
295
237
  this.initialized = true;
296
238
  });
@@ -367,21 +309,18 @@ class LayoutService {
367
309
  reset() {
368
310
  this.resetSource.next(true);
369
311
  }
370
- // Config & state updates
371
312
  updateLayoutConfig(config) {
372
313
  this._layoutConfig.update((prev) => ({ ...prev, ...config }));
373
314
  }
374
315
  updateLayoutState(state) {
375
316
  this._layoutState.update((prev) => ({ ...prev, ...state }));
376
317
  }
377
- // Profile setters
378
318
  setUserProfile(profile) {
379
319
  this._userProfile.set(profile);
380
320
  }
381
321
  setCompanyProfile(profile) {
382
322
  this._companyProfile.set(profile);
383
323
  }
384
- // Menu & apps
385
324
  setMenu(items) {
386
325
  this._rawMenu.set(items);
387
326
  }
@@ -457,6 +396,82 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
457
396
  }]
458
397
  }] });
459
398
 
399
+ const _presets = { Aura, Lara, Nora };
400
+ const _noirPrimary = {
401
+ 50: '{surface.50}', 100: '{surface.100}', 200: '{surface.200}',
402
+ 300: '{surface.300}', 400: '{surface.400}', 500: '{surface.500}',
403
+ 600: '{surface.600}', 700: '{surface.700}', 800: '{surface.800}',
404
+ 900: '{surface.900}', 950: '{surface.950}',
405
+ };
406
+ const _noraScheme = {
407
+ light: {
408
+ primary: { color: '{primary.600}', contrastColor: '#ffffff', hoverColor: '{primary.700}', activeColor: '{primary.800}' },
409
+ highlight: { background: '{primary.600}', focusBackground: '{primary.700}', color: '#ffffff', focusColor: '#ffffff' },
410
+ },
411
+ dark: {
412
+ primary: { color: '{primary.500}', contrastColor: '{surface.900}', hoverColor: '{primary.400}', activeColor: '{primary.300}' },
413
+ highlight: { background: '{primary.500}', focusBackground: '{primary.400}', color: '{surface.900}', focusColor: '{surface.900}' },
414
+ },
415
+ };
416
+ const _defaultScheme = {
417
+ light: {
418
+ primary: { color: '{primary.500}', contrastColor: '#ffffff', hoverColor: '{primary.600}', activeColor: '{primary.700}' },
419
+ highlight: { background: '{primary.50}', focusBackground: '{primary.100}', color: '{primary.700}', focusColor: '{primary.800}' },
420
+ },
421
+ dark: {
422
+ primary: { color: '{primary.400}', contrastColor: '{surface.900}', hoverColor: '{primary.300}', activeColor: '{primary.200}' },
423
+ highlight: {
424
+ background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
425
+ focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
426
+ color: 'rgba(255,255,255,.87)',
427
+ focusColor: 'rgba(255,255,255,.87)',
428
+ },
429
+ },
430
+ };
431
+ function buildSemanticExt(palette, presetName) {
432
+ if (palette === null) {
433
+ return {
434
+ semantic: {
435
+ primary: _noirPrimary,
436
+ colorScheme: {
437
+ light: {
438
+ primary: { color: '{primary.950}', contrastColor: '#ffffff', hoverColor: '{primary.800}', activeColor: '{primary.700}' },
439
+ highlight: { background: '{primary.950}', focusBackground: '{primary.700}', color: '#ffffff', focusColor: '#ffffff' },
440
+ },
441
+ dark: {
442
+ primary: { color: '{primary.50}', contrastColor: '{primary.950}', hoverColor: '{primary.200}', activeColor: '{primary.300}' },
443
+ highlight: { background: '{primary.50}', focusBackground: '{primary.300}', color: '{primary.950}', focusColor: '{primary.950}' },
444
+ },
445
+ },
446
+ },
447
+ };
448
+ }
449
+ return { semantic: { primary: palette, colorScheme: presetName === 'Nora' ? _noraScheme : _defaultScheme } };
450
+ }
451
+ function buildPreset(presetName, primary) {
452
+ const base = _presets[presetName in _presets ? presetName : 'Aura'];
453
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
454
+ const palette = primary === 'noir' ? null : base.primitive?.[primary];
455
+ if (primary !== 'noir' && !palette)
456
+ return base;
457
+ return definePreset(base, buildSemanticExt(palette, presetName));
458
+ }
459
+ function buildBootstrapPreset(envConfig) {
460
+ const preset = envConfig?.preset ?? 'Aura';
461
+ const primary = envConfig?.primary ?? 'violet';
462
+ if (envConfig?.isMemorable !== false) {
463
+ try {
464
+ const stored = localStorage.getItem('flusys.layout.config');
465
+ if (stored) {
466
+ const parsed = JSON.parse(stored);
467
+ return buildPreset(parsed.preset ?? preset, parsed.primary ?? primary);
468
+ }
469
+ }
470
+ catch { /* SSR or storage disabled */ }
471
+ }
472
+ return buildPreset(preset, primary);
473
+ }
474
+
460
475
  const presets = {
461
476
  Aura,
462
477
  Lara,
@@ -464,9 +479,8 @@ const presets = {
464
479
  };
465
480
  class AppConfigurator {
466
481
  router = inject(Router);
467
- translateAdapter = inject(TranslateService, {
468
- optional: true,
469
- });
482
+ translateAdapter = inject(TranslateService, { optional: true });
483
+ platformId = inject(PLATFORM_ID);
470
484
  layoutService = inject(LayoutService);
471
485
  presets = Object.keys(presets);
472
486
  showMenuModeButton = signal(!this.router.url.includes('auth'), ...(ngDevMode ? [{ debugName: "showMenuModeButton" }] : []));
@@ -481,7 +495,6 @@ class AppConfigurator {
481
495
  value: 'overlay',
482
496
  },
483
497
  ];
484
- // Only show topbar mode on desktop
485
498
  if (this.layoutService.isDesktop()) {
486
499
  options.push({
487
500
  label: this.translate('layout.configurator.menu.mode.topbar'),
@@ -491,11 +504,10 @@ class AppConfigurator {
491
504
  return options;
492
505
  }, ...(ngDevMode ? [{ debugName: "menuModeOptions" }] : []));
493
506
  constructor() {
494
- // Use afterNextRender for browser-only initialization (replaces isServer check)
495
- afterNextRender(() => {
507
+ if (isPlatformBrowser(this.platformId)) {
496
508
  const preset = this.layoutService.layoutConfig().preset ?? 'Aura';
497
509
  this.onPresetChange(preset);
498
- });
510
+ }
499
511
  }
500
512
  surfaces = [
501
513
  {
@@ -635,9 +647,7 @@ class AppConfigurator {
635
647
  },
636
648
  },
637
649
  ];
638
- selectedPrimaryColor = computed(() => {
639
- return this.layoutService.layoutConfig().primary;
640
- }, ...(ngDevMode ? [{ debugName: "selectedPrimaryColor" }] : []));
650
+ selectedPrimaryColor = computed(() => this.layoutService.layoutConfig().primary, ...(ngDevMode ? [{ debugName: "selectedPrimaryColor" }] : []));
641
651
  selectedSurfaceColor = computed(() => this.layoutService.layoutConfig().surface, ...(ngDevMode ? [{ debugName: "selectedSurfaceColor" }] : []));
642
652
  isSurfaceSelected(surfaceName) {
643
653
  const selectedSurface = this.selectedSurfaceColor();
@@ -681,133 +691,10 @@ class AppConfigurator {
681
691
  return palettes;
682
692
  }, ...(ngDevMode ? [{ debugName: "primaryColors" }] : []));
683
693
  getPresetExt() {
684
- const color = this.primaryColors().find((c) => c.name === this.selectedPrimaryColor()) || {};
685
- const preset = this.layoutService.layoutConfig().preset;
686
- if (color.name === 'noir') {
687
- return {
688
- semantic: {
689
- primary: {
690
- 50: '{surface.50}',
691
- 100: '{surface.100}',
692
- 200: '{surface.200}',
693
- 300: '{surface.300}',
694
- 400: '{surface.400}',
695
- 500: '{surface.500}',
696
- 600: '{surface.600}',
697
- 700: '{surface.700}',
698
- 800: '{surface.800}',
699
- 900: '{surface.900}',
700
- 950: '{surface.950}',
701
- },
702
- colorScheme: {
703
- light: {
704
- primary: {
705
- color: '{primary.950}',
706
- contrastColor: '#ffffff',
707
- hoverColor: '{primary.800}',
708
- activeColor: '{primary.700}',
709
- },
710
- highlight: {
711
- background: '{primary.950}',
712
- focusBackground: '{primary.700}',
713
- color: '#ffffff',
714
- focusColor: '#ffffff',
715
- },
716
- },
717
- dark: {
718
- primary: {
719
- color: '{primary.50}',
720
- contrastColor: '{primary.950}',
721
- hoverColor: '{primary.200}',
722
- activeColor: '{primary.300}',
723
- },
724
- highlight: {
725
- background: '{primary.50}',
726
- focusBackground: '{primary.300}',
727
- color: '{primary.950}',
728
- focusColor: '{primary.950}',
729
- },
730
- },
731
- },
732
- },
733
- };
734
- }
735
- else {
736
- if (preset === 'Nora') {
737
- return {
738
- semantic: {
739
- primary: color.palette,
740
- colorScheme: {
741
- light: {
742
- primary: {
743
- color: '{primary.600}',
744
- contrastColor: '#ffffff',
745
- hoverColor: '{primary.700}',
746
- activeColor: '{primary.800}',
747
- },
748
- highlight: {
749
- background: '{primary.600}',
750
- focusBackground: '{primary.700}',
751
- color: '#ffffff',
752
- focusColor: '#ffffff',
753
- },
754
- },
755
- dark: {
756
- primary: {
757
- color: '{primary.500}',
758
- contrastColor: '{surface.900}',
759
- hoverColor: '{primary.400}',
760
- activeColor: '{primary.300}',
761
- },
762
- highlight: {
763
- background: '{primary.500}',
764
- focusBackground: '{primary.400}',
765
- color: '{surface.900}',
766
- focusColor: '{surface.900}',
767
- },
768
- },
769
- },
770
- },
771
- };
772
- }
773
- else {
774
- return {
775
- semantic: {
776
- primary: color.palette,
777
- colorScheme: {
778
- light: {
779
- primary: {
780
- color: '{primary.500}',
781
- contrastColor: '#ffffff',
782
- hoverColor: '{primary.600}',
783
- activeColor: '{primary.700}',
784
- },
785
- highlight: {
786
- background: '{primary.50}',
787
- focusBackground: '{primary.100}',
788
- color: '{primary.700}',
789
- focusColor: '{primary.800}',
790
- },
791
- },
792
- dark: {
793
- primary: {
794
- color: '{primary.400}',
795
- contrastColor: '{surface.900}',
796
- hoverColor: '{primary.300}',
797
- activeColor: '{primary.200}',
798
- },
799
- highlight: {
800
- background: 'color-mix(in srgb, {primary.400}, transparent 84%)',
801
- focusBackground: 'color-mix(in srgb, {primary.400}, transparent 76%)',
802
- color: 'rgba(255,255,255,.87)',
803
- focusColor: 'rgba(255,255,255,.87)',
804
- },
805
- },
806
- },
807
- },
808
- };
809
- }
810
- }
694
+ const color = this.primaryColors().find(c => c.name === this.selectedPrimaryColor()) ?? {};
695
+ const preset = this.layoutService.layoutConfig().preset ?? 'Aura';
696
+ const palette = color.name === 'noir' ? null : (color.palette ?? {});
697
+ return buildSemanticExt(palette, preset);
811
698
  }
812
699
  updateColors(event, type, color) {
813
700
  if (type === 'primary') {
@@ -3025,8 +2912,13 @@ const LAYOUT_MESSAGES = {
3025
2912
  'menu.forms': 'Forms',
3026
2913
  'menu.email': 'Email',
3027
2914
  'menu.event.manager': 'Event Manager',
2915
+ 'menu.task.manager': 'Task Manager',
3028
2916
  'menu.notifications': 'Notifications',
3029
2917
  'menu.localization': 'Localization',
2918
+ 'menu.projects': 'Projects',
2919
+ 'menu.projects.active': 'Active Projects',
2920
+ 'menu.projects.archived': 'Archived',
2921
+ 'menu.projects.reports': 'Reports',
3030
2922
  // Those are layout part from notification module, but we put them here to avoid circular dependency between layout and notification module
3031
2923
  // components/notification-bell/notification-bell.component.ts
3032
2924
  'notification.title': 'Notifications',
@@ -3047,5 +2939,5 @@ const LAYOUT_MESSAGES = {
3047
2939
  * Generated bundle index. Do not edit.
3048
2940
  */
3049
2941
 
3050
- export { AppCompanyBranchSelector, AppConfigurator, AppFloatingConfigurator, AppFooter, AppLauncher, AppLayout, AppMenu, AppMenuitem, AppProfile, AppSearchbar, AppSidebar, AppTopbar, GreenTheme, LAYOUT_AUTH_API, LAYOUT_AUTH_STATE, LAYOUT_IS_RTL, LAYOUT_LANGUAGE_SELECTOR, LAYOUT_LANGUAGE_SELECTOR_PANEL, LAYOUT_MESSAGES, LAYOUT_NOTIFICATION_BELL, LAYOUT_SEARCHBAR, LAYOUT_SEARCH_ADAPTER, LayoutPersistenceService, LayoutService, NavyBlueTheme, filterAppsByPermissions, filterMenuByPermissions };
2942
+ export { AppCompanyBranchSelector, AppConfigurator, AppFloatingConfigurator, AppFooter, AppLauncher, AppLayout, AppMenu, AppMenuitem, AppProfile, AppSearchbar, AppSidebar, AppTopbar, GreenTheme, LAYOUT_AUTH_API, LAYOUT_AUTH_STATE, LAYOUT_IS_RTL, LAYOUT_LANGUAGE_SELECTOR, LAYOUT_LANGUAGE_SELECTOR_PANEL, LAYOUT_MESSAGES, LAYOUT_NOTIFICATION_BELL, LAYOUT_SEARCHBAR, LAYOUT_SEARCH_ADAPTER, LayoutPersistenceService, LayoutService, NavyBlueTheme, buildBootstrapPreset, buildPreset, buildSemanticExt, filterAppsByPermissions, filterMenuByPermissions };
3051
2943
  //# sourceMappingURL=flusys-ng-layout.mjs.map