@memberjunction/ng-explorer-settings 6.1.4 → 6.2.0-edge.1

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.
Files changed (77) hide show
  1. package/dist/lib/account-info/account-info.component.d.ts +1 -1
  2. package/dist/lib/account-info/account-info.component.js +2 -2
  3. package/dist/lib/account-info/account-info.component.js.map +1 -1
  4. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts +93 -10
  5. package/dist/lib/application-management/application-dialog/application-dialog.component.d.ts.map +1 -1
  6. package/dist/lib/application-management/application-dialog/application-dialog.component.js +232 -80
  7. package/dist/lib/application-management/application-dialog/application-dialog.component.js.map +1 -1
  8. package/dist/lib/application-management/application-management.component.d.ts +94 -11
  9. package/dist/lib/application-management/application-management.component.d.ts.map +1 -1
  10. package/dist/lib/application-management/application-management.component.js +231 -67
  11. package/dist/lib/application-management/application-management.component.js.map +1 -1
  12. package/dist/lib/application-settings/application-settings.component.d.ts +4 -4
  13. package/dist/lib/application-settings/application-settings.component.js +10 -10
  14. package/dist/lib/application-settings/application-settings.component.js.map +1 -1
  15. package/dist/lib/entity-permissions/entity-permissions.component.d.ts +88 -10
  16. package/dist/lib/entity-permissions/entity-permissions.component.d.ts.map +1 -1
  17. package/dist/lib/entity-permissions/entity-permissions.component.js +219 -63
  18. package/dist/lib/entity-permissions/entity-permissions.component.js.map +1 -1
  19. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts +44 -6
  20. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.d.ts.map +1 -1
  21. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js +117 -43
  22. package/dist/lib/entity-permissions/permission-dialog/permission-dialog.component.js.map +1 -1
  23. package/dist/lib/notification-preferences/notification-preferences.component.d.ts +25 -3
  24. package/dist/lib/notification-preferences/notification-preferences.component.d.ts.map +1 -1
  25. package/dist/lib/notification-preferences/notification-preferences.component.js +62 -18
  26. package/dist/lib/notification-preferences/notification-preferences.component.js.map +1 -1
  27. package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts +32 -4
  28. package/dist/lib/role-management/role-dialog/role-dialog.component.d.ts.map +1 -1
  29. package/dist/lib/role-management/role-dialog/role-dialog.component.js +84 -30
  30. package/dist/lib/role-management/role-dialog/role-dialog.component.js.map +1 -1
  31. package/dist/lib/role-management/role-management-agent-context.d.ts +12 -4
  32. package/dist/lib/role-management/role-management-agent-context.d.ts.map +1 -1
  33. package/dist/lib/role-management/role-management-agent-context.js +26 -10
  34. package/dist/lib/role-management/role-management-agent-context.js.map +1 -1
  35. package/dist/lib/role-management/role-management.component.d.ts +95 -11
  36. package/dist/lib/role-management/role-management.component.d.ts.map +1 -1
  37. package/dist/lib/role-management/role-management.component.js +259 -91
  38. package/dist/lib/role-management/role-management.component.js.map +1 -1
  39. package/dist/lib/settings/settings.component.d.ts +87 -11
  40. package/dist/lib/settings/settings.component.d.ts.map +1 -1
  41. package/dist/lib/settings/settings.component.js +211 -65
  42. package/dist/lib/settings/settings.component.js.map +1 -1
  43. package/dist/lib/shared/settings-card.component.d.ts +24 -4
  44. package/dist/lib/shared/settings-card.component.d.ts.map +1 -1
  45. package/dist/lib/shared/settings-card.component.js +46 -6
  46. package/dist/lib/shared/settings-card.component.js.map +1 -1
  47. package/dist/lib/sql-logging/sql-logging.component.d.ts +172 -18
  48. package/dist/lib/sql-logging/sql-logging.component.d.ts.map +1 -1
  49. package/dist/lib/sql-logging/sql-logging.component.js +320 -108
  50. package/dist/lib/sql-logging/sql-logging.component.js.map +1 -1
  51. package/dist/lib/user-app-config/user-app-config-content.component.js +3 -3
  52. package/dist/lib/user-app-config/user-app-config-content.component.js.map +1 -1
  53. package/dist/lib/user-app-config/user-app-config-reorder.d.ts +4 -0
  54. package/dist/lib/user-app-config/user-app-config-reorder.d.ts.map +1 -1
  55. package/dist/lib/user-app-config/user-app-config-reorder.js +11 -3
  56. package/dist/lib/user-app-config/user-app-config-reorder.js.map +1 -1
  57. package/dist/lib/user-management/transaction-group-refusals.d.ts +45 -0
  58. package/dist/lib/user-management/transaction-group-refusals.d.ts.map +1 -0
  59. package/dist/lib/user-management/transaction-group-refusals.js +49 -0
  60. package/dist/lib/user-management/transaction-group-refusals.js.map +1 -0
  61. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts +44 -6
  62. package/dist/lib/user-management/user-dialog/user-dialog.component.d.ts.map +1 -1
  63. package/dist/lib/user-management/user-dialog/user-dialog.component.js +134 -45
  64. package/dist/lib/user-management/user-dialog/user-dialog.component.js.map +1 -1
  65. package/dist/lib/user-management/user-management-agent-context.d.ts +10 -0
  66. package/dist/lib/user-management/user-management-agent-context.d.ts.map +1 -1
  67. package/dist/lib/user-management/user-management-agent-context.js +26 -6
  68. package/dist/lib/user-management/user-management-agent-context.js.map +1 -1
  69. package/dist/lib/user-management/user-management.component.d.ts +174 -16
  70. package/dist/lib/user-management/user-management.component.d.ts.map +1 -1
  71. package/dist/lib/user-management/user-management.component.js +501 -177
  72. package/dist/lib/user-management/user-management.component.js.map +1 -1
  73. package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts +97 -15
  74. package/dist/lib/user-profile-settings/user-profile-settings.component.d.ts.map +1 -1
  75. package/dist/lib/user-profile-settings/user-profile-settings.component.js +280 -116
  76. package/dist/lib/user-profile-settings/user-profile-settings.component.js.map +1 -1
  77. package/package.json +20 -20
@@ -265,19 +265,75 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
265
265
  location;
266
266
  cdr;
267
267
  ngZone;
268
- stateChange = new EventEmitter();
268
+ StateChange = new EventEmitter();
269
+ /**
270
+ * @deprecated Use {@link StateChange}.
271
+ *
272
+ * The same emitter under the old binding name, so a template still binding
273
+ * (stateChange) keeps working. Must stay AFTER StateChange: class fields
274
+ * initialise in order, and the other way round this captures undefined.
275
+ */
276
+ stateChange = this.StateChange;
269
277
  // State management
270
- activeTab = 'general';
271
- searchTerm$ = new BehaviorSubject('');
278
+ ActiveTab = 'general';
279
+ /** @deprecated Use {@link ActiveTab}. */
280
+ get activeTab() {
281
+ return this.ActiveTab;
282
+ }
283
+ /** @deprecated Use {@link ActiveTab}. */
284
+ set activeTab(value) {
285
+ this.ActiveTab = value;
286
+ }
287
+ SearchTerm$ = new BehaviorSubject('');
288
+ /** @deprecated Use {@link SearchTerm$}. */
289
+ get searchTerm$() {
290
+ return this.SearchTerm$;
291
+ }
292
+ /** @deprecated Use {@link SearchTerm$}. */
293
+ set searchTerm$(value) {
294
+ this.SearchTerm$ = value;
295
+ }
272
296
  isLoading = false;
273
297
  error = null;
274
298
  // Search state
275
- filteredTabs = [];
276
- searchResults = [];
277
- isSearching = false;
278
- showSearchResults = false;
299
+ FilteredTabs = [];
300
+ /** @deprecated Use {@link FilteredTabs}. */
301
+ get filteredTabs() {
302
+ return this.FilteredTabs;
303
+ }
304
+ /** @deprecated Use {@link FilteredTabs}. */
305
+ set filteredTabs(value) {
306
+ this.FilteredTabs = value;
307
+ }
308
+ SearchResults = [];
309
+ /** @deprecated Use {@link SearchResults}. */
310
+ get searchResults() {
311
+ return this.SearchResults;
312
+ }
313
+ /** @deprecated Use {@link SearchResults}. */
314
+ set searchResults(value) {
315
+ this.SearchResults = value;
316
+ }
317
+ IsSearching = false;
318
+ /** @deprecated Use {@link IsSearching}. */
319
+ get isSearching() {
320
+ return this.IsSearching;
321
+ }
322
+ /** @deprecated Use {@link IsSearching}. */
323
+ set isSearching(value) {
324
+ this.IsSearching = value;
325
+ }
326
+ ShowSearchResults = false;
327
+ /** @deprecated Use {@link ShowSearchResults}. */
328
+ get showSearchResults() {
329
+ return this.ShowSearchResults;
330
+ }
331
+ /** @deprecated Use {@link ShowSearchResults}. */
332
+ set showSearchResults(value) {
333
+ this.ShowSearchResults = value;
334
+ }
279
335
  // Tab configuration - User-focused tabs only
280
- tabs = [
336
+ Tabs = [
281
337
  {
282
338
  id: 'general',
283
339
  label: 'General',
@@ -304,6 +360,14 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
304
360
  disabled: true
305
361
  }
306
362
  ];
363
+ /** @deprecated Use {@link Tabs}. */
364
+ get tabs() {
365
+ return this.Tabs;
366
+ }
367
+ /** @deprecated Use {@link Tabs}. */
368
+ set tabs(value) {
369
+ this.Tabs = value;
370
+ }
307
371
  // Searchable content registry - User settings only
308
372
  searchableItems = [
309
373
  // General tab
@@ -352,10 +416,34 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
352
416
  }
353
417
  ];
354
418
  // Section expansion state
355
- expandedSections = ['profile', 'account'];
419
+ ExpandedSections = ['profile', 'account'];
420
+ /** @deprecated Use {@link ExpandedSections}. */
421
+ get expandedSections() {
422
+ return this.ExpandedSections;
423
+ }
424
+ /** @deprecated Use {@link ExpandedSections}. */
425
+ set expandedSections(value) {
426
+ this.ExpandedSections = value;
427
+ }
356
428
  // Mobile state
357
- isMobile = window.innerWidth < 768;
358
- isMobileNavOpen = false;
429
+ IsMobile = window.innerWidth < 768;
430
+ /** @deprecated Use {@link IsMobile}. */
431
+ get isMobile() {
432
+ return this.IsMobile;
433
+ }
434
+ /** @deprecated Use {@link IsMobile}. */
435
+ set isMobile(value) {
436
+ this.IsMobile = value;
437
+ }
438
+ IsMobileNavOpen = false;
439
+ /** @deprecated Use {@link IsMobileNavOpen}. */
440
+ get isMobileNavOpen() {
441
+ return this.IsMobileNavOpen;
442
+ }
443
+ /** @deprecated Use {@link IsMobileNavOpen}. */
444
+ set isMobileNavOpen(value) {
445
+ this.IsMobileNavOpen = value;
446
+ }
359
447
  destroy$ = new Subject();
360
448
  constructor(location, cdr, ngZone) {
361
449
  super();
@@ -365,9 +453,9 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
365
453
  window.addEventListener('resize', this.handleResize.bind(this));
366
454
  }
367
455
  ngOnInit() {
368
- this.filteredTabs = [...this.tabs];
456
+ this.FilteredTabs = [...this.Tabs];
369
457
  this.setupSearchFilter();
370
- this.loadInitialData();
458
+ this.LoadInitialData();
371
459
  }
372
460
  ngOnDestroy() {
373
461
  this.destroy$.next();
@@ -375,14 +463,14 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
375
463
  window.removeEventListener('resize', this.handleResize.bind(this));
376
464
  }
377
465
  setupSearchFilter() {
378
- this.searchTerm$
466
+ this.SearchTerm$
379
467
  .pipe(debounceTime(200), distinctUntilChanged(), takeUntil(this.destroy$))
380
468
  .subscribe(term => {
381
469
  this.filterContent(term);
382
470
  this.emitStateChange();
383
471
  });
384
472
  }
385
- async loadInitialData() {
473
+ async LoadInitialData() {
386
474
  try {
387
475
  this.isLoading = true;
388
476
  await this.simulateDataLoad();
@@ -399,140 +487,188 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
399
487
  });
400
488
  }
401
489
  }
490
+ /** @deprecated Use {@link LoadInitialData}. */
491
+ async loadInitialData() {
492
+ return this.LoadInitialData();
493
+ }
402
494
  async simulateDataLoad() {
403
495
  return new Promise(resolve => setTimeout(resolve, 300));
404
496
  }
405
- onTabChange(tabId) {
406
- const tab = this.tabs.find(t => t.id === tabId);
497
+ OnTabChange(tabId) {
498
+ const tab = this.Tabs.find(t => t.id === tabId);
407
499
  if (tab?.disabled) {
408
500
  return; // Don't switch to disabled tabs
409
501
  }
410
- this.activeTab = tabId;
502
+ this.ActiveTab = tabId;
411
503
  this.emitStateChange();
412
504
  }
413
- onSearchChange(event) {
505
+ /** @deprecated Use {@link OnTabChange}. */
506
+ onTabChange(tabId) {
507
+ return this.OnTabChange(tabId);
508
+ }
509
+ OnSearchChange(event) {
414
510
  const term = event.target.value;
415
- this.searchTerm$.next(term);
511
+ this.SearchTerm$.next(term);
512
+ }
513
+ /** @deprecated Use {@link OnSearchChange}. */
514
+ onSearchChange(event) {
515
+ return this.OnSearchChange(event);
416
516
  }
417
517
  toggleSection(sectionId) {
418
- const index = this.expandedSections.indexOf(sectionId);
518
+ const index = this.ExpandedSections.indexOf(sectionId);
419
519
  if (index === -1) {
420
- this.expandedSections.push(sectionId);
520
+ this.ExpandedSections.push(sectionId);
421
521
  }
422
522
  else {
423
- this.expandedSections.splice(index, 1);
523
+ this.ExpandedSections.splice(index, 1);
424
524
  }
425
525
  this.emitStateChange();
426
526
  }
527
+ IsSectionExpanded(sectionId) {
528
+ return this.ExpandedSections.includes(sectionId);
529
+ }
530
+ /** @deprecated Use {@link IsSectionExpanded}. */
427
531
  isSectionExpanded(sectionId) {
428
- return this.expandedSections.includes(sectionId);
532
+ return this.IsSectionExpanded(sectionId);
429
533
  }
430
534
  /**
431
535
  * Filters searchable content based on search term
432
536
  */
433
537
  filterContent(term) {
434
538
  if (!term || term.trim() === '') {
435
- this.showSearchResults = false;
436
- this.searchResults = [];
437
- this.filteredTabs = [...this.tabs];
539
+ this.ShowSearchResults = false;
540
+ this.SearchResults = [];
541
+ this.FilteredTabs = [...this.Tabs];
438
542
  return;
439
543
  }
440
544
  const searchLower = term.toLowerCase().trim();
441
- this.isSearching = true;
545
+ this.IsSearching = true;
442
546
  // Filter searchable items
443
- this.searchResults = this.searchableItems.filter(item => {
547
+ this.SearchResults = this.searchableItems.filter(item => {
444
548
  const matchesLabel = item.label.toLowerCase().includes(searchLower);
445
549
  const matchesKeywords = item.keywords.some(kw => kw.toLowerCase().includes(searchLower));
446
550
  const matchesDescription = item.description?.toLowerCase().includes(searchLower) || false;
447
551
  return matchesLabel || matchesKeywords || matchesDescription;
448
552
  });
449
553
  // Get unique tabs that have matching results
450
- const matchingTabIds = new Set(this.searchResults.map(r => r.tabId));
451
- this.filteredTabs = this.tabs.filter(tab => matchingTabIds.has(tab.id));
452
- this.showSearchResults = true;
453
- this.isSearching = false;
554
+ const matchingTabIds = new Set(this.SearchResults.map(r => r.tabId));
555
+ this.FilteredTabs = this.Tabs.filter(tab => matchingTabIds.has(tab.id));
556
+ this.ShowSearchResults = true;
557
+ this.IsSearching = false;
454
558
  }
455
559
  /**
456
560
  * Navigates to a search result
457
561
  */
458
- navigateToSearchResult(result) {
459
- const tab = this.tabs.find(t => t.id === result.tabId);
562
+ NavigateToSearchResult(result) {
563
+ const tab = this.Tabs.find(t => t.id === result.tabId);
460
564
  if (tab?.disabled) {
461
565
  return; // Don't navigate to disabled tabs
462
566
  }
463
- this.activeTab = result.tabId;
567
+ this.ActiveTab = result.tabId;
464
568
  // Expand the section if applicable
465
- if (result.sectionId && !this.expandedSections.includes(result.sectionId)) {
466
- this.expandedSections.push(result.sectionId);
569
+ if (result.sectionId && !this.ExpandedSections.includes(result.sectionId)) {
570
+ this.ExpandedSections.push(result.sectionId);
467
571
  }
468
- this.clearSearch();
572
+ this.ClearSearch();
469
573
  this.emitStateChange();
470
574
  }
575
+ /** @deprecated Use {@link NavigateToSearchResult}. */
576
+ navigateToSearchResult(result) {
577
+ return this.NavigateToSearchResult(result);
578
+ }
471
579
  /**
472
580
  * Clears the search and resets the view
473
581
  */
582
+ ClearSearch() {
583
+ this.SearchTerm$.next('');
584
+ this.ShowSearchResults = false;
585
+ this.SearchResults = [];
586
+ this.FilteredTabs = [...this.Tabs];
587
+ }
588
+ /** @deprecated Use {@link ClearSearch}. */
474
589
  clearSearch() {
475
- this.searchTerm$.next('');
476
- this.showSearchResults = false;
477
- this.searchResults = [];
478
- this.filteredTabs = [...this.tabs];
590
+ return this.ClearSearch();
479
591
  }
480
592
  /**
481
593
  * Toggles the mobile navigation rail
482
594
  */
595
+ ToggleMobileNav() {
596
+ this.IsMobileNavOpen = !this.IsMobileNavOpen;
597
+ }
598
+ /** @deprecated Use {@link ToggleMobileNav}. */
483
599
  toggleMobileNav() {
484
- this.isMobileNavOpen = !this.isMobileNavOpen;
600
+ return this.ToggleMobileNav();
485
601
  }
486
602
  /**
487
603
  * Closes the mobile navigation rail
488
604
  */
605
+ CloseMobileNav() {
606
+ this.IsMobileNavOpen = false;
607
+ }
608
+ /** @deprecated Use {@link CloseMobileNav}. */
489
609
  closeMobileNav() {
490
- this.isMobileNavOpen = false;
610
+ return this.CloseMobileNav();
491
611
  }
492
612
  /**
493
613
  * Closes the settings page and navigates back
494
614
  */
495
- closeSettings() {
615
+ CloseSettings() {
496
616
  this.location.back();
497
617
  }
618
+ /** @deprecated Use {@link CloseSettings}. */
619
+ closeSettings() {
620
+ return this.CloseSettings();
621
+ }
498
622
  /**
499
623
  * Handles tab change on mobile
500
624
  */
625
+ OnMobileTabChange(tabId) {
626
+ this.OnTabChange(tabId);
627
+ this.CloseMobileNav();
628
+ }
629
+ /** @deprecated Use {@link OnMobileTabChange}. */
501
630
  onMobileTabChange(tabId) {
502
- this.onTabChange(tabId);
503
- this.closeMobileNav();
631
+ return this.OnMobileTabChange(tabId);
504
632
  }
505
633
  handleResize() {
506
- this.isMobile = window.innerWidth < 768;
507
- if (!this.isMobile) {
508
- this.isMobileNavOpen = false;
634
+ this.IsMobile = window.innerWidth < 768;
635
+ if (!this.IsMobile) {
636
+ this.IsMobileNavOpen = false;
509
637
  }
510
638
  }
511
639
  emitStateChange() {
512
640
  const state = {
513
- activeTab: this.activeTab,
514
- searchTerm: this.searchTerm$.value,
515
- expandedSections: [...this.expandedSections]
641
+ activeTab: this.ActiveTab,
642
+ searchTerm: this.SearchTerm$.value,
643
+ expandedSections: [...this.ExpandedSections]
516
644
  };
517
- this.stateChange.emit(state);
645
+ this.StateChange.emit(state);
518
646
  }
519
- loadUserState(state) {
647
+ LoadUserState(state) {
520
648
  if (state.activeTab) {
521
- this.activeTab = state.activeTab;
649
+ this.ActiveTab = state.activeTab;
522
650
  }
523
651
  if (state.searchTerm !== undefined) {
524
- this.searchTerm$.next(state.searchTerm);
652
+ this.SearchTerm$.next(state.searchTerm);
525
653
  }
526
654
  if (state.expandedSections) {
527
- this.expandedSections = [...state.expandedSections];
655
+ this.ExpandedSections = [...state.expandedSections];
528
656
  }
529
657
  }
530
- getTabIcon(tab) {
658
+ /** @deprecated Use {@link LoadUserState}. */
659
+ loadUserState(state) {
660
+ return this.LoadUserState(state);
661
+ }
662
+ GetTabIcon(tab) {
531
663
  return tab.icon;
532
664
  }
533
- getTabClass(tab) {
665
+ /** @deprecated Use {@link GetTabIcon}. */
666
+ getTabIcon(tab) {
667
+ return this.GetTabIcon(tab);
668
+ }
669
+ GetTabClass(tab) {
534
670
  const classes = ['settings-tab'];
535
- if (this.activeTab === tab.id) {
671
+ if (this.ActiveTab === tab.id) {
536
672
  classes.push('active');
537
673
  }
538
674
  if (tab.disabled) {
@@ -543,11 +679,19 @@ let SettingsComponent = class SettingsComponent extends BaseNavigationComponent
543
679
  }
544
680
  return classes.join(' ');
545
681
  }
546
- isTabDisabled(tab) {
682
+ /** @deprecated Use {@link GetTabClass}. */
683
+ getTabClass(tab) {
684
+ return this.GetTabClass(tab);
685
+ }
686
+ IsTabDisabled(tab) {
547
687
  return tab.disabled || false;
548
688
  }
689
+ /** @deprecated Use {@link IsTabDisabled}. */
690
+ isTabDisabled(tab) {
691
+ return this.IsTabDisabled(tab);
692
+ }
549
693
  static ɵfac = function SettingsComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || SettingsComponent)(i0.ɵɵdirectiveInject(i1.Location), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone)); };
550
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], outputs: { stateChange: "stateChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [[1, "mj-page-container"], ["role", "status", "aria-live", "polite", 1, "loading-container"], ["role", "alert", 1, "error-container"], [1, "settings-content"], ["text", "Loading settings..."], [1, "error-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "desktop-layout", 2, "display", "flex"], [1, "mobile-layout"], ["role", "navigation", "aria-label", "Settings navigation", 1, "side-navigation"], [1, "nav-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "nav-search-icon"], ["type", "text", "placeholder", "Search settings...", "aria-label", "Search settings", 1, "nav-search-input", 3, "input", "value"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear"], ["role", "tablist", "aria-orientation", "vertical", 1, "nav-list"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "active", "disabled"], ["role", "tabpanel", 1, "content-area"], [1, "tab-content"], [1, "notifications-settings"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "click", "keydown.enter"], ["aria-hidden", "true"], [1, "nav-label"], [1, "coming-soon-badge"], [1, "nav-badge", 3, "class"], [1, "nav-badge"], [1, "section-title"], [1, "section-description"], [1, "mobile-header"], ["aria-hidden", "true", 1, "mobile-nav-backdrop"], ["role", "navigation", "aria-label", "Settings navigation", 1, "mobile-nav-rail"], [1, "nav-rail-header"], [1, "nav-rail-title"], ["role", "tablist", 1, "nav-rail-items"], ["role", "tab", 1, "nav-rail-item", 3, "active", "disabled"], ["aria-label", "Close settings", 1, "nav-rail-item", "nav-rail-close-item", 3, "click"], [1, "nav-rail-label"], [1, "mobile-content"], ["aria-label", "Toggle navigation menu", 1, "mobile-header-icon", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-bars"], [1, "mobile-header-title"], [1, "mobile-header-spacer"], ["aria-hidden", "true", 1, "mobile-nav-backdrop", 3, "click"], ["role", "tab", 1, "nav-rail-item", 3, "click", "disabled"], [1, "rail-badge", 3, "class"], [1, "rail-badge"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
694
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: SettingsComponent, selectors: [["mj-settings"]], outputs: { StateChange: "StateChange", stateChange: "stateChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [[1, "mj-page-container"], ["role", "status", "aria-live", "polite", 1, "loading-container"], ["role", "alert", 1, "error-container"], [1, "settings-content"], ["text", "Loading settings..."], [1, "error-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-exclamation-triangle", "error-icon"], [1, "error-message"], [1, "retry-button", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-refresh"], [1, "desktop-layout", 2, "display", "flex"], [1, "mobile-layout"], ["role", "navigation", "aria-label", "Settings navigation", 1, "side-navigation"], [1, "nav-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-search", "nav-search-icon"], ["type", "text", "placeholder", "Search settings...", "aria-label", "Search settings", 1, "nav-search-input", 3, "input", "value"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear"], ["role", "tablist", "aria-orientation", "vertical", 1, "nav-list"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "active", "disabled"], ["role", "tabpanel", 1, "content-area"], [1, "tab-content"], [1, "notifications-settings"], ["aria-label", "Clear search", "tabindex", "0", 1, "nav-search-clear", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["role", "tab", "tabindex", "0", 1, "nav-item", 3, "click", "keydown.enter"], ["aria-hidden", "true"], [1, "nav-label"], [1, "coming-soon-badge"], [1, "nav-badge", 3, "class"], [1, "nav-badge"], [1, "section-title"], [1, "section-description"], [1, "mobile-header"], ["aria-hidden", "true", 1, "mobile-nav-backdrop"], ["role", "navigation", "aria-label", "Settings navigation", 1, "mobile-nav-rail"], [1, "nav-rail-header"], [1, "nav-rail-title"], ["role", "tablist", 1, "nav-rail-items"], ["role", "tab", 1, "nav-rail-item", 3, "active", "disabled"], ["aria-label", "Close settings", 1, "nav-rail-item", "nav-rail-close-item", 3, "click"], [1, "nav-rail-label"], [1, "mobile-content"], ["aria-label", "Toggle navigation menu", 1, "mobile-header-icon", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-bars"], [1, "mobile-header-title"], [1, "mobile-header-spacer"], ["aria-hidden", "true", 1, "mobile-nav-backdrop", 3, "click"], ["role", "tab", 1, "nav-rail-item", 3, "click", "disabled"], [1, "rail-badge", 3, "class"], [1, "rail-badge"]], template: function SettingsComponent_Template(rf, ctx) { if (rf & 1) {
551
695
  i0.ɵɵelementStart(0, "div", 0);
552
696
  i0.ɵɵconditionalCreate(1, SettingsComponent_Conditional_1_Template, 2, 0, "div", 1);
553
697
  i0.ɵɵconditionalCreate(2, SettingsComponent_Conditional_2_Template, 8, 1, "div", 2);
@@ -569,7 +713,9 @@ export { SettingsComponent };
569
713
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SettingsComponent, [{
570
714
  type: Component,
571
715
  args: [{ standalone: false, selector: 'mj-settings', template: "<div class=\"mj-page-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\" role=\"status\" aria-live=\"polite\">\n <mj-loading text=\"Loading settings...\"></mj-loading>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-container\" role=\"alert\">\n <div class=\"error-content\">\n <i class=\"fa-solid fa-exclamation-triangle error-icon\" aria-hidden=\"true\"></i>\n <p class=\"error-message\">{{ error }}</p>\n <button class=\"retry-button\" (click)=\"loadInitialData()\">\n <i class=\"fa-solid fa-refresh\" aria-hidden=\"true\"></i>\n Try Again\n </button>\n </div>\n </div>\n }\n\n <!-- Main Content -->\n @if (!isLoading && !error) {\n <div class=\"settings-content\">\n <!-- Desktop Layout -->\n @if (!isMobile) {\n <div class=\"desktop-layout\" style=\"display: flex;\">\n <!-- Side Navigation -->\n <nav class=\"side-navigation\" role=\"navigation\" aria-label=\"Settings navigation\">\n <!-- Search Bar -->\n <div class=\"nav-search\">\n <i class=\"fa-solid fa-search nav-search-icon\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n class=\"nav-search-input\"\n placeholder=\"Search settings...\"\n (input)=\"onSearchChange($event)\"\n [value]=\"searchTerm$.value\"\n aria-label=\"Search settings\"\n />\n @if (searchTerm$.value) {\n <button\n class=\"nav-search-clear\"\n (click)=\"clearSearch()\"\n aria-label=\"Clear search\"\n tabindex=\"0\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n\n <ul class=\"nav-list\" role=\"tablist\" aria-orientation=\"vertical\">\n @for (tab of filteredTabs; track tab.id) {\n <li\n class=\"nav-item\"\n [class.active]=\"activeTab === tab.id\"\n [class.disabled]=\"tab.disabled\"\n (click)=\"onTabChange(tab.id)\"\n (keydown.enter)=\"onTabChange(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.id\"\n [attr.aria-controls]=\"'panel-' + tab.id\"\n [attr.aria-disabled]=\"tab.disabled\"\n tabindex=\"0\"\n >\n <i [class]=\"tab.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-label\">{{ tab.label }}</span>\n @if (tab.disabled) {\n <span class=\"coming-soon-badge\">Soon</span>\n }\n @if (tab.badgeCount && tab.badgeCount > 0) {\n <span class=\"nav-badge\" [class]=\"'badge-' + (tab.badgeColor || 'primary')\">\n {{ tab.badgeCount }}\n </span>\n }\n </li>\n }\n </ul>\n </nav>\n\n <!-- Content Area -->\n <div class=\"content-area\" role=\"tabpanel\" [attr.id]=\"'panel-' + activeTab\">\n <div class=\"tab-content\">\n @switch (activeTab) {\n @case ('general') {\n <mj-general-settings></mj-general-settings>\n }\n\n @case ('notifications') {\n <div class=\"notifications-settings\">\n <h2 class=\"section-title\">Notifications</h2>\n <p class=\"section-description\">Configure how and when you receive notifications</p>\n <mj-notification-preferences></mj-notification-preferences>\n </div>\n }\n\n @case ('applications') {\n <mj-application-settings></mj-application-settings>\n }\n\n @case ('appearance') {\n <mj-appearance-settings></mj-appearance-settings>\n }\n }\n </div>\n </div>\n </div>\n }\n\n <!-- Mobile Layout -->\n @if (isMobile) {\n <div class=\"mobile-layout\">\n <!-- Mobile Header -->\n @if (!isMobileNavOpen) {\n <header class=\"mobile-header\">\n <button\n class=\"mobile-header-icon\"\n (click)=\"toggleMobileNav()\"\n aria-label=\"Toggle navigation menu\"\n [attr.aria-expanded]=\"isMobileNavOpen\"\n >\n <i class=\"fa-solid fa-bars\" aria-hidden=\"true\"></i>\n </button>\n <h1 class=\"mobile-header-title\">Settings</h1>\n <div class=\"mobile-header-spacer\"></div>\n </header>\n }\n\n <!-- Backdrop Overlay -->\n @if (isMobileNavOpen) {\n <div\n class=\"mobile-nav-backdrop\"\n (click)=\"closeMobileNav()\"\n aria-hidden=\"true\"\n ></div>\n }\n\n <!-- Mobile Navigation Rail -->\n <nav\n class=\"mobile-nav-rail\"\n [class.open]=\"isMobileNavOpen\"\n role=\"navigation\"\n aria-label=\"Settings navigation\"\n >\n <div class=\"nav-rail-header\">\n <span class=\"nav-rail-title\">Settings</span>\n </div>\n\n <div class=\"nav-rail-items\" role=\"tablist\">\n @for (tab of filteredTabs; track tab.id) {\n <button\n class=\"nav-rail-item\"\n [class.active]=\"activeTab === tab.id\"\n [class.disabled]=\"tab.disabled\"\n [disabled]=\"tab.disabled\"\n (click)=\"onMobileTabChange(tab.id)\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === tab.id\"\n [attr.aria-label]=\"tab.label\"\n >\n <i [class]=\"tab.icon\" aria-hidden=\"true\"></i>\n <span class=\"nav-rail-label\">{{ tab.label }}</span>\n @if (tab.disabled) {\n <span class=\"coming-soon-badge\">Soon</span>\n }\n @if (tab.badgeCount && tab.badgeCount > 0) {\n <span class=\"rail-badge\" [class]=\"'badge-' + (tab.badgeColor || 'primary')\">\n {{ tab.badgeCount }}\n </span>\n }\n </button>\n }\n\n <button\n class=\"nav-rail-item nav-rail-close-item\"\n (click)=\"closeSettings()\"\n aria-label=\"Close settings\"\n >\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n <span class=\"nav-rail-label\">Close</span>\n </button>\n </div>\n </nav>\n\n <!-- Mobile Content Area -->\n <div class=\"mobile-content\">\n <div class=\"tab-content\">\n @switch (activeTab) {\n @case ('general') {\n <mj-general-settings></mj-general-settings>\n }\n\n @case ('notifications') {\n <div class=\"notifications-settings\">\n <h2 class=\"section-title\">Notifications</h2>\n <p class=\"section-description\">Configure how and when you receive notifications</p>\n <mj-notification-preferences></mj-notification-preferences>\n </div>\n }\n\n @case ('applications') {\n <mj-application-settings></mj-application-settings>\n }\n\n @case ('appearance') {\n <mj-appearance-settings></mj-appearance-settings>\n }\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n</div>\n", styles: ["/* ============================================\n Settings Component\n Using MJ Design Tokens\n ============================================ */\n\n/* ============================================\n Host & Page Container\n ============================================ */\n\n/* Host element must fill its container */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n@media (max-width: 768px) {\n :host {\n height: auto;\n min-height: 100vh;\n overflow: visible;\n }\n}\n\n/* Page container needs proper height and scrolling */\n.mj-page-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n@media (max-width: 768px) {\n .mj-page-container {\n overflow-y: visible;\n overflow-x: hidden;\n height: auto;\n min-height: 100vh;\n }\n}\n\n/* ============================================\n Keyframe Animations\n ============================================ */\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n\n/* ============================================\n Settings Container & Main Layout\n ============================================ */\n\n.settings-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n background-color: var(--mj-bg-page);\n overflow-y: auto;\n position: relative;\n}\n\n/* ============================================\n Loading State\n ============================================ */\n.loading-container {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n}\n\n.loading-content {\n text-align: center;\n}\n\n.loading-text {\n color: var(--mj-text-muted);\n font-size: 1rem;\n}\n\n/* ============================================\n Error State\n ============================================ */\n.error-container {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2rem;\n}\n\n.error-content {\n text-align: center;\n max-width: 400px;\n}\n\n.error-content .error-icon {\n font-size: 3rem;\n color: var(--mj-status-error);\n margin-bottom: 1rem;\n}\n\n.error-content .error-message {\n color: var(--mj-text-primary);\n margin-bottom: 1.5rem;\n font-size: 1rem;\n}\n\n.error-content .retry-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem 1.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n border: none;\n border-radius: 20px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n white-space: nowrap;\n min-height: 44px;\n background-color: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n}\n\n.error-content .retry-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.error-content .retry-button:hover:not(:disabled) {\n background-color: var(--mj-brand-primary);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08);\n}\n\n.error-content .retry-button i {\n font-size: 0.875rem;\n}\n\n/* ============================================\n Main Content Area & Tab Layout\n ============================================ */\n\n.settings-content {\n display: flex;\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n flex-direction: column;\n width: 100%;\n min-height: 0;\n}\n\n@media (max-width: 768px) {\n .settings-content {\n overflow-y: visible;\n overflow-x: hidden;\n height: auto;\n min-height: 0;\n flex: none;\n }\n}\n\n.desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n.settings-content .desktop-layout {\n display: flex !important;\n height: 100%;\n width: 100%;\n}\n\n/* ============================================\n Side Navigation (Desktop Only)\n ============================================ */\n\n.side-navigation {\n width: 280px;\n background: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n overflow-y: auto;\n flex-shrink: 0;\n box-shadow: var(--mj-shadow-sm);\n}\n\n/* Navigation Search Bar */\n.nav-search {\n position: relative;\n padding: 1rem;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface);\n}\n\n.nav-search-icon {\n position: absolute;\n left: 1.75rem;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-muted);\n font-size: 1rem;\n pointer-events: none;\n z-index: 1;\n}\n\n.nav-search-input {\n width: 100%;\n padding: 0.75rem 2.75rem 0.75rem 2.5rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 9999px;\n font-size: 0.875rem;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n background-color: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.nav-search-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n background-color: var(--mj-bg-surface);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.nav-search-input::placeholder {\n color: var(--mj-text-muted);\n}\n\n.nav-search-clear {\n position: absolute;\n right: 1.25rem;\n top: 50%;\n transform: translateY(-50%);\n padding: 0.25rem;\n background: transparent;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n border-radius: 9999px;\n min-width: 32px;\n min-height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n z-index: 1;\n}\n\n.nav-search-clear:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.nav-search-clear:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.nav-list {\n list-style: none;\n margin: 0;\n padding: 1rem 0;\n}\n\n.nav-item {\n position: relative;\n display: flex;\n align-items: center;\n padding: 1rem 1.5rem;\n margin: 0.25rem 0.75rem;\n border-radius: 12px;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n color: var(--mj-text-muted);\n font-size: 1rem;\n border: 2px solid transparent;\n}\n\n.nav-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n transform: translateX(4px);\n}\n\n.nav-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Color-coded navigation items */\n.nav-item[aria-controls=\"panel-general\"] {\n --item-color: var(--mj-brand-primary);\n --item-container: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-users\"] {\n --item-color: var(--mj-status-warning);\n --item-container: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-roles\"] {\n --item-color: var(--mj-status-success);\n --item-container: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-applications\"] {\n --item-color: var(--mj-brand-primary);\n --item-container: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-permissions\"] {\n --item-color: var(--mj-status-error);\n --item-container: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n}\n\n.nav-item[aria-controls=\"panel-advanced\"] {\n --item-color: var(--mj-status-warning);\n --item-container: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n}\n\n.nav-item.active {\n background-color: var(--item-container);\n color: var(--item-color);\n font-weight: 600;\n border-color: var(--item-color);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.nav-item:hover:not(.active) {\n border-color: var(--item-color);\n background-color: var(--mj-bg-surface-card);\n}\n\n.nav-item i {\n width: 20px;\n margin-right: 0.75rem;\n font-size: 1.1rem;\n}\n\n.nav-item .nav-label {\n flex: 1;\n}\n\n.nav-item .nav-badge {\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.nav-item .nav-badge.badge-primary {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.nav-item .nav-badge.badge-danger {\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.nav-item .nav-badge.badge-warning {\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.nav-item .nav-badge.badge-success {\n background-color: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n/* Disabled Navigation Items */\n.nav-item.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nav-item.disabled:hover {\n background-color: transparent;\n transform: none;\n}\n\n/* Coming Soon Badge */\n.coming-soon-badge {\n display: inline-flex;\n align-items: center;\n padding: 0.125rem 0.5rem;\n border-radius: 9999px;\n font-size: 0.625rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid var(--mj-border-default);\n}\n\n/* Mobile Navigation Disabled Items */\n.nav-rail-item.disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nav-rail-item.disabled:hover {\n background-color: transparent;\n}\n\n/* ============================================\n Content Area & Tab Panels\n ============================================ */\n\n.content-area {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 0;\n background: var(--mj-bg-surface);\n}\n\n@media (max-width: 768px) {\n .content-area {\n padding: 1rem;\n }\n}\n\n.tab-content {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n max-width: 100%;\n min-height: 0;\n box-sizing: border-box;\n overflow-x: hidden;\n padding: 1.5rem 2rem;\n}\n\n@media (max-width: 768px) {\n .tab-content {\n height: auto;\n min-height: 0;\n overflow-y: visible;\n overflow-x: hidden;\n padding: 0.5rem;\n }\n}\n\n/* ============================================\n Section Titles\n ============================================ */\n.section-title {\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 1rem 0;\n padding-bottom: 0.75rem;\n border-bottom: 3px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.section-title::before {\n content: \"\";\n width: 4px;\n height: 2rem;\n background: var(--mj-brand-primary);\n border-radius: 2px;\n}\n\n.section-description {\n color: var(--mj-text-muted);\n margin: 0 0 1.5rem 0;\n font-size: 1rem;\n padding: 1rem 1.25rem;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n}\n\n/* ============================================\n Settings Grid\n ============================================ */\n.settings-grid,\n.mj-grid {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n margin-top: 1.5rem;\n}\n\n.mj-grid-responsive {\n /* Single column stacked layout */\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n@media (max-width: 768px) {\n .settings-grid,\n .mj-grid,\n .mj-grid-responsive {\n gap: 1rem;\n margin-top: 0.5rem;\n }\n}\n\n/* ============================================\n Section Title & Description Spacing\n ============================================ */\n.general-settings .section-title,\n.users-settings .section-title,\n.roles-settings .section-title {\n margin-bottom: 0.25rem;\n}\n\n.users-settings .section-description,\n.roles-settings .section-description {\n margin-bottom: 0.5rem;\n}\n\n/* ============================================\n Card Content\n ============================================ */\n.card-content {\n padding: 1rem;\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n}\n\n.card-content p {\n margin: 0 0 1rem 0;\n line-height: 1.6;\n}\n\n/* ============================================\n Beta Warning\n ============================================ */\n.beta-warning {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1.25rem;\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border-radius: 12px;\n font-size: 0.875rem;\n font-weight: 600;\n margin-bottom: 1.5rem;\n max-width: 100%;\n box-sizing: border-box;\n border: 2px solid var(--mj-status-warning);\n box-shadow: 0 2px 8px rgba(255, 111, 0, 0.2);\n}\n\n.beta-warning i {\n font-size: 1rem;\n flex-shrink: 0;\n}\n\n@media (max-width: 768px) {\n .beta-warning {\n font-size: 0.8125rem;\n padding: 0.5rem 0.75rem;\n margin-bottom: 0.75rem;\n }\n}\n\n/* ============================================\n Mobile Layout with Collapsible Navigation Rail\n ============================================ */\n\n.mobile-layout {\n position: relative;\n display: flex;\n flex-direction: column;\n min-height: 100vh;\n width: 100%;\n max-width: 100vw;\n overflow: visible;\n box-sizing: border-box;\n}\n\n/* Mobile Header */\n.mobile-header {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 56px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0.5rem;\n background-color: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n z-index: 100;\n box-sizing: border-box;\n}\n\n.mobile-header-icon {\n width: 48px;\n height: 48px;\n min-width: 48px;\n border-radius: 9999px;\n background: transparent;\n color: var(--mj-text-primary);\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.mobile-header-icon:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.mobile-header-icon:active {\n transform: scale(0.95);\n}\n\n.mobile-header-icon i {\n font-size: 1.25rem;\n}\n\n.mobile-header-title {\n flex: 1;\n text-align: center;\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n padding: 0 0.5rem;\n}\n\n.mobile-header-spacer {\n width: 48px;\n min-width: 48px;\n}\n\n/* Backdrop Overlay */\n.mobile-nav-backdrop {\n position: fixed;\n inset: 0;\n background-color: rgba(0, 0, 0, 0.5);\n z-index: 1000;\n animation: fadeIn 0.2s ease-out;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Collapsible Navigation Rail */\n.mobile-nav-rail {\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 80vw;\n background-color: var(--mj-bg-surface);\n border-right: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n z-index: 1001;\n transform: translateX(-100%);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow: var(--mj-shadow-lg);\n overflow: hidden;\n}\n\n.mobile-nav-rail.open {\n transform: translateX(0);\n}\n\n/* Navigation Rail Header */\n.nav-rail-header {\n display: flex;\n align-items: center;\n padding: 1rem 1.5rem;\n min-height: 64px;\n border-bottom: 1px solid var(--mj-border-default);\n background-color: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.nav-rail-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n/* Navigation Items Container */\n.nav-rail-items {\n display: flex;\n flex-direction: column;\n padding: 0.5rem;\n gap: 0.25rem;\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n}\n\n/* Close Navigation Item */\n.nav-rail-close-item {\n margin-top: auto;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 0.75rem !important;\n margin-top: 0.5rem;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)) !important;\n color: var(--mj-status-error) !important;\n}\n\n.nav-rail-close-item:hover {\n background-color: var(--mj-status-error) !important;\n color: var(--mj-bg-surface) !important;\n}\n\n.nav-rail-close-item i {\n font-size: 1.5rem;\n}\n\n/* Navigation Item */\n.nav-rail-item {\n position: relative;\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 1rem;\n width: 100%;\n padding: 0.875rem 1rem;\n background: transparent;\n border: none;\n border-radius: 12px;\n color: var(--mj-text-muted);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n text-align: left;\n min-height: 56px;\n}\n\n.nav-rail-item i {\n font-size: 1.5rem;\n width: 24px;\n text-align: center;\n flex-shrink: 0;\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.nav-rail-label {\n font-size: 1rem;\n font-weight: 500;\n flex: 1;\n}\n\n.nav-rail-item:hover:not(.active) {\n background-color: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.nav-rail-item.active {\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.nav-rail-item.active .nav-rail-label {\n font-weight: 600;\n}\n\n.nav-rail-item:active {\n transform: scale(0.98);\n}\n\n.nav-rail-item:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Badge indicator */\n.rail-badge {\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 9999px;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.rail-badge.badge-primary {\n background-color: var(--mj-brand-primary);\n color: var(--mj-bg-surface);\n}\n\n.rail-badge.badge-danger {\n background-color: var(--mj-status-error);\n color: var(--mj-bg-surface);\n}\n\n.rail-badge.badge-warning {\n background-color: var(--mj-status-success);\n color: var(--mj-bg-surface);\n}\n\n.rail-badge.badge-success {\n background-color: var(--mj-status-warning);\n color: var(--mj-text-primary);\n}\n\n/* Mobile Content Area */\n.mobile-content {\n width: 100%;\n max-width: 100vw;\n overflow-y: visible;\n overflow-x: hidden;\n padding: 72px 0.75rem 2rem 0.75rem;\n min-width: 0;\n box-sizing: border-box;\n -webkit-overflow-scrolling: touch;\n flex: 1;\n}\n\n/* Responsive adjustments */\n@media (max-width: 374px) {\n .mobile-nav-rail {\n width: 260px;\n }\n\n .mobile-content {\n padding: 64px 0.5rem 1.5rem 0.5rem;\n }\n\n .mobile-header {\n height: 52px;\n padding: 0 0.25rem;\n }\n\n .mobile-header-icon {\n width: 44px;\n height: 44px;\n min-width: 44px;\n }\n\n .mobile-header-spacer {\n width: 44px;\n min-width: 44px;\n }\n\n .mobile-header-title {\n font-size: 1.125rem;\n }\n}\n\n/* ============================================\n Advanced Settings Sub-Tabs\n ============================================ */\n\n.advanced-tabs {\n display: flex;\n gap: 0.5rem;\n border-bottom: 2px solid var(--mj-border-default);\n margin-bottom: 1rem;\n margin-top: 1rem;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n -webkit-overflow-scrolling: touch;\n}\n\n.advanced-tabs .tab-btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1rem;\n background: transparent;\n border: none;\n border-bottom: 3px solid transparent;\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n position: relative;\n min-height: 44px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Mobile-specific tab adjustments - Segmented Button Style */\n@media (max-width: 768px) {\n .advanced-tabs {\n gap: 0;\n margin-bottom: 1rem;\n margin-top: 1rem;\n border-bottom: none;\n border: 1px solid var(--mj-border-strong);\n border-radius: 9999px;\n padding: 0;\n background-color: var(--mj-bg-surface-sunken);\n overflow-x: hidden;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n }\n\n .advanced-tabs .tab-btn {\n flex: 1;\n padding: 0.625rem 0.5rem;\n font-size: 0.75rem;\n border-bottom: none;\n border-radius: 0;\n border-right: 1px solid var(--mj-border-strong);\n min-width: 0;\n justify-content: center;\n text-align: center;\n white-space: nowrap;\n overflow: hidden;\n }\n\n .advanced-tabs .tab-btn:last-child {\n border-right: none;\n }\n\n .advanced-tabs .tab-btn:first-child {\n border-radius: 9999px 0 0 9999px;\n }\n\n .advanced-tabs .tab-btn:last-child {\n border-radius: 0 9999px 9999px 0;\n }\n\n .advanced-tabs .tab-btn.active {\n background-color: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border-bottom: none;\n }\n\n .advanced-tabs .tab-btn i {\n font-size: 0.875rem;\n }\n}\n\n.advanced-tabs .tab-btn:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.advanced-tabs .tab-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -2px;\n}\n\n.advanced-tabs .tab-btn.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.advanced-tabs .tab-btn.active i {\n color: var(--mj-brand-primary);\n}\n\n.advanced-tabs .tab-btn i {\n font-size: 1.125rem;\n}\n\n/* ============================================\n Advanced Tab Content Panels\n ============================================ */\n\n.advanced-tab-content {\n flex: 1;\n overflow-y: visible;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n background: var(--mj-bg-surface);\n border-radius: 16px;\n padding: 0;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n/* Ensure scrolling works on mobile */\n@media (max-width: 768px) {\n .advanced-tab-content {\n height: auto;\n min-height: 200px;\n overflow-y: visible;\n }\n}\n\n.performance-settings,\n.developer-settings {\n padding: 2rem;\n}\n\n.performance-settings h3,\n.developer-settings h3 {\n margin: 0 0 1rem 0;\n font-size: 1.25rem;\n color: var(--mj-text-primary);\n}\n\n.performance-settings p,\n.developer-settings p {\n color: var(--mj-text-muted);\n font-size: 1rem;\n}\n\n/* ============================================\n Settings Panel Containers with Fade-In Animation\n ============================================ */\n\n.general-settings,\n.users-settings,\n.roles-settings,\n.applications-settings,\n.permissions-settings,\n.advanced-settings {\n animation: fadeIn 0.3s ease-out;\n width: 100%;\n max-width: 100%;\n height: auto;\n min-height: 100%;\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n overflow-y: visible;\n overflow-x: hidden;\n box-sizing: border-box;\n}\n\n/* Mobile-specific adjustments */\n@media (max-width: 768px) {\n .general-settings,\n .users-settings,\n .roles-settings,\n .applications-settings,\n .permissions-settings,\n .advanced-settings {\n gap: 0.75rem;\n height: auto;\n min-height: auto;\n }\n\n .section-title {\n margin-bottom: 0.5rem;\n font-size: 1.375rem;\n }\n\n .section-description {\n margin-bottom: 0.75rem;\n }\n}\n\n/* Only apply flex: 1 to actual content components, not titles/descriptions */\n.general-settings > mj-settings-card,\n.general-settings > .mj-grid,\n.users-settings > mj-user-management,\n.roles-settings > mj-role-management,\n.applications-settings > mj-application-management,\n.permissions-settings > mj-entity-permissions,\n.advanced-settings > .advanced-tabs,\n.advanced-settings > .advanced-tab-content {\n flex-shrink: 0;\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n}\n\n/* Allow content to flow naturally on mobile */\n@media (max-width: 768px) {\n .users-settings > mj-user-management,\n .roles-settings > mj-role-management,\n .applications-settings > mj-application-management,\n .permissions-settings > mj-entity-permissions,\n .advanced-settings > .advanced-tab-content {\n flex: none;\n height: auto !important;\n min-height: 0;\n max-height: none !important;\n overflow-y: visible !important;\n overflow-x: hidden;\n }\n}\n\n/* Titles and descriptions should not flex or grow */\n.general-settings > .section-title,\n.users-settings > .section-title,\n.roles-settings > .section-title,\n.users-settings > .section-description,\n.roles-settings > .section-description {\n flex-shrink: 0;\n flex-grow: 0;\n}\n\n/* ============================================\n Accessibility: Reduced Motion Support\n ============================================ */\n\n@media (prefers-reduced-motion: reduce) {\n .general-settings,\n .users-settings,\n .roles-settings,\n .applications-settings,\n .permissions-settings,\n .advanced-settings {\n animation: none;\n }\n\n .nav-tab i,\n .nav-item,\n .tab-btn,\n .search-input,\n .retry-button,\n .search-result-item {\n transition: none;\n }\n}\n\n/* ============================================\n Responsive Breakpoints\n ============================================ */\n@media (max-width: 640px) {\n .side-navigation {\n width: 200px;\n }\n\n .nav-item {\n padding: 0.75rem 1rem;\n }\n}\n\n@media (max-width: 1024px) {\n .content-area {\n padding: 1.5rem;\n }\n}\n\n/* Mobile scroll fix - ensure all child components flow naturally */\n@media (max-width: 768px) {\n .mobile-layout mj-user-management,\n .mobile-layout mj-role-management,\n .mobile-layout mj-application-management,\n .mobile-layout mj-entity-permissions,\n .mobile-layout mj-sql-logging,\n .mobile-layout mj-settings-card,\n .mobile-layout mj-user-profile-settings {\n display: block;\n height: auto !important;\n max-height: none !important;\n overflow: visible !important;\n }\n\n /* Ensure all nested content areas flow naturally */\n .mobile-layout .general-settings,\n .mobile-layout .users-settings,\n .mobile-layout .roles-settings,\n .mobile-layout .applications-settings,\n .mobile-layout .permissions-settings,\n .mobile-layout .advanced-settings {\n height: auto !important;\n min-height: 0 !important;\n max-height: none !important;\n }\n\n /* Ensure mj-grid and card content can expand */\n .mobile-layout .mj-grid,\n .mobile-layout .mj-grid-responsive,\n .mobile-layout .card-content {\n height: auto !important;\n min-height: 0 !important;\n }\n}\n\n@media (min-width: 1440px) {\n .content-area {\n padding: 2.5rem 3rem;\n }\n\n .side-navigation {\n width: 280px;\n }\n}\n\n/* ============================================\n iOS Safari Mobile Scrolling Fix\n ============================================ */\n@media (max-width: 768px) {\n /* Prevent iOS from restricting body scrolling */\n body {\n position: relative;\n overflow-y: visible;\n -webkit-overflow-scrolling: touch;\n }\n\n /* Allow mobile layout and all parents to expand naturally */\n .mobile-layout,\n .mobile-layout > *,\n .mobile-content > *,\n .tab-content > * {\n -webkit-overflow-scrolling: touch;\n }\n\n /* Prevent fixed heights from blocking scroll */\n .mobile-layout * {\n box-sizing: border-box;\n }\n}\n"] }]
572
- }], () => [{ type: i1.Location }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], { stateChange: [{
716
+ }], () => [{ type: i1.Location }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], { StateChange: [{
717
+ type: Output
718
+ }], stateChange: [{
573
719
  type: Output
574
720
  }] }); })();
575
721
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SettingsComponent, { className: "SettingsComponent", filePath: "src/lib/settings/settings.component.ts", lineNumber: 41 }); })();