@memberjunction/ng-explorer-core 5.47.0 → 5.49.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.
- package/dist/generated/lazy-feature-config.d.ts +1 -1
- package/dist/generated/lazy-feature-config.d.ts.map +1 -1
- package/dist/generated/lazy-feature-config.js +132 -128
- package/dist/generated/lazy-feature-config.js.map +1 -1
- package/dist/lib/omnibar/index.d.ts +15 -0
- package/dist/lib/omnibar/index.d.ts.map +1 -0
- package/dist/lib/omnibar/index.js +24 -0
- package/dist/lib/omnibar/index.js.map +1 -0
- package/dist/lib/omnibar/omnibar-palette.component.d.ts +130 -0
- package/dist/lib/omnibar/omnibar-palette.component.d.ts.map +1 -0
- package/dist/lib/omnibar/omnibar-palette.component.js +838 -0
- package/dist/lib/omnibar/omnibar-palette.component.js.map +1 -0
- package/dist/lib/omnibar/omnibar-provider.d.ts +94 -0
- package/dist/lib/omnibar/omnibar-provider.d.ts.map +1 -0
- package/dist/lib/omnibar/omnibar-provider.js +84 -0
- package/dist/lib/omnibar/omnibar-provider.js.map +1 -0
- package/dist/lib/omnibar/omnibar-shortcut.d.ts +12 -0
- package/dist/lib/omnibar/omnibar-shortcut.d.ts.map +1 -0
- package/dist/lib/omnibar/omnibar-shortcut.js +16 -0
- package/dist/lib/omnibar/omnibar-shortcut.js.map +1 -0
- package/dist/lib/omnibar/omnibar-user-setting.d.ts +38 -0
- package/dist/lib/omnibar/omnibar-user-setting.d.ts.map +1 -0
- package/dist/lib/omnibar/omnibar-user-setting.js +53 -0
- package/dist/lib/omnibar/omnibar-user-setting.js.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-agent.provider.d.ts +24 -0
- package/dist/lib/omnibar/providers/omnibar-agent.provider.d.ts.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-agent.provider.js +69 -0
- package/dist/lib/omnibar/providers/omnibar-agent.provider.js.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-command.provider.d.ts +29 -0
- package/dist/lib/omnibar/providers/omnibar-command.provider.d.ts.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-command.provider.js +130 -0
- package/dist/lib/omnibar/providers/omnibar-command.provider.js.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts +35 -0
- package/dist/lib/omnibar/providers/omnibar-record.provider.d.ts.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-record.provider.js +176 -0
- package/dist/lib/omnibar/providers/omnibar-record.provider.js.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts +21 -0
- package/dist/lib/omnibar/providers/omnibar-search.provider.d.ts.map +1 -0
- package/dist/lib/omnibar/providers/omnibar-search.provider.js +94 -0
- package/dist/lib/omnibar/providers/omnibar-search.provider.js.map +1 -0
- package/dist/lib/profile/profile-dialog.component.d.ts +29 -0
- package/dist/lib/profile/profile-dialog.component.d.ts.map +1 -1
- package/dist/lib/profile/profile-dialog.component.js +325 -78
- package/dist/lib/profile/profile-dialog.component.js.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +16 -0
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +66 -6
- package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
- package/dist/lib/resource-wrappers/view-resource.component.js +6 -2
- package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts +7 -0
- package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
- package/dist/lib/shell/components/tabs/tab-container.component.js +26 -4
- package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
- package/dist/lib/shell/shell.component.d.ts +76 -10
- package/dist/lib/shell/shell.component.d.ts.map +1 -1
- package/dist/lib/shell/shell.component.js +503 -270
- package/dist/lib/shell/shell.component.js.map +1 -1
- package/dist/lib/shell/shell.module.d.ts +8 -7
- package/dist/lib/shell/shell.module.d.ts.map +1 -1
- package/dist/lib/shell/shell.module.js +5 -2
- package/dist/lib/shell/shell.module.js.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
- package/dist/lib/single-list-detail/single-list-detail.component.js +39 -27
- package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +52 -50
|
@@ -6,10 +6,12 @@ import { LogStatus, LogError, StartupManager, CompositeKey } from '@memberjuncti
|
|
|
6
6
|
import { MJEventType, MJGlobal, uuidv4, UUIDsEqual } from '@memberjunction/global';
|
|
7
7
|
import { EventCodes, SharedService, SYSTEM_APP_ID } from '@memberjunction/ng-shared';
|
|
8
8
|
import { MJNotificationService } from '@memberjunction/ng-notifications';
|
|
9
|
+
import { IsOmnibarAvailable, IsOmnibarEnabledForUser, OMNIBAR_PROMO_DISMISSED_KEY, OMNIBAR_USER_SETTING_KEY } from '../omnibar/omnibar-user-setting';
|
|
10
|
+
import { GetOmnibarShortcutLabel } from '../omnibar/omnibar-shortcut';
|
|
9
11
|
import { getActiveTheme } from './loading-themes';
|
|
10
12
|
import { TabContainerComponent } from './components/tabs/tab-container.component';
|
|
11
13
|
import { BaseUserMenu, isUserMenuDivider } from '../user-menu';
|
|
12
|
-
import { InstanceConfigEngine } from '@memberjunction/core-entities';
|
|
14
|
+
import { InstanceConfigEngine, UserInfoEngine } from '@memberjunction/core-entities';
|
|
13
15
|
import { PACKAGE_VERSION } from '@memberjunction/graphql-dataprovider';
|
|
14
16
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
15
17
|
import * as i0 from "@angular/core";
|
|
@@ -34,13 +36,15 @@ import * as i18 from "./components/header/app-nav.component";
|
|
|
34
36
|
import * as i19 from "./components/tabs/tab-container.component";
|
|
35
37
|
import * as i20 from "./components/dialogs/app-access-dialog.component";
|
|
36
38
|
import * as i21 from "../command-palette/command-palette.component";
|
|
39
|
+
import * as i22 from "../omnibar/omnibar-palette.component";
|
|
37
40
|
const _c0 = ["searchInput"];
|
|
38
|
-
const _c1 = ["
|
|
39
|
-
const _c2 = ["
|
|
41
|
+
const _c1 = ["omnibarPalette"];
|
|
42
|
+
const _c2 = ["shellSearchComposite"];
|
|
43
|
+
const _c3 = ["appAccessDialog"];
|
|
40
44
|
const _forTrack0 = ($index, $item) => $item.ID;
|
|
41
45
|
function ShellComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
42
46
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
43
|
-
i0.ɵɵelementStart(0, "button",
|
|
47
|
+
i0.ɵɵelementStart(0, "button", 46);
|
|
44
48
|
i0.ɵɵlistener("click", function ShellComponent_Conditional_5_For_2_Template_button_click_0_listener($event) { const app_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r3, $event)); })("dblclick", function ShellComponent_Conditional_5_For_2_Template_button_dblclick_0_listener($event) { const app_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r3, $event)); });
|
|
45
49
|
i0.ɵɵelement(1, "i");
|
|
46
50
|
i0.ɵɵelementEnd();
|
|
@@ -54,8 +58,8 @@ function ShellComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
54
58
|
i0.ɵɵclassMap(app_r3.Icon);
|
|
55
59
|
} }
|
|
56
60
|
function ShellComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
57
|
-
i0.ɵɵelementStart(0, "div",
|
|
58
|
-
i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_5_For_2_Template, 2, 7, "button",
|
|
61
|
+
i0.ɵɵelementStart(0, "div", 9);
|
|
62
|
+
i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_5_For_2_Template, 2, 7, "button", 45, i0.ɵɵrepeaterTrackByIdentity);
|
|
59
63
|
i0.ɵɵelementEnd();
|
|
60
64
|
} if (rf & 2) {
|
|
61
65
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -64,7 +68,7 @@ function ShellComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
|
64
68
|
} }
|
|
65
69
|
function ShellComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
66
70
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
67
|
-
i0.ɵɵelementStart(0, "mj-app-switcher",
|
|
71
|
+
i0.ɵɵelementStart(0, "mj-app-switcher", 47);
|
|
68
72
|
i0.ɵɵlistener("appSelected", function ShellComponent_Conditional_6_Template_mj_app_switcher_appSelected_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onAppSwitch($event)); });
|
|
69
73
|
i0.ɵɵelementEnd();
|
|
70
74
|
} if (rf & 2) {
|
|
@@ -73,25 +77,54 @@ function ShellComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
|
73
77
|
} }
|
|
74
78
|
function ShellComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
75
79
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
76
|
-
i0.ɵɵelementStart(0, "mj-app-nav",
|
|
80
|
+
i0.ɵɵelementStart(0, "mj-app-nav", 48);
|
|
77
81
|
i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_7_Template_mj_app_nav_navItemClick_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_7_Template_mj_app_nav_navItemDismiss_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
|
|
78
82
|
i0.ɵɵelementEnd();
|
|
79
83
|
} if (rf & 2) {
|
|
80
84
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
81
85
|
i0.ɵɵproperty("app", ctx_r3.activeApp);
|
|
82
86
|
} }
|
|
83
|
-
function
|
|
87
|
+
function ShellComponent_Conditional_10_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
84
88
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
85
|
-
i0.ɵɵelementStart(0, "
|
|
86
|
-
i0.ɵɵlistener("
|
|
89
|
+
i0.ɵɵelementStart(0, "button", 50);
|
|
90
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_10_Conditional_0_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnHeaderSearchClick()); });
|
|
91
|
+
i0.ɵɵelement(1, "i", 51);
|
|
92
|
+
i0.ɵɵelementStart(2, "span", 52);
|
|
93
|
+
i0.ɵɵtext(3, "Search everything");
|
|
94
|
+
i0.ɵɵelementEnd();
|
|
95
|
+
i0.ɵɵelementStart(4, "kbd", 53);
|
|
96
|
+
i0.ɵɵtext(5);
|
|
87
97
|
i0.ɵɵelementEnd()();
|
|
88
98
|
} if (rf & 2) {
|
|
89
|
-
const ctx_r3 = i0.ɵɵnextContext();
|
|
99
|
+
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
100
|
+
i0.ɵɵattribute("aria-label", "Search everything (" + ctx_r3.OmnibarShortcutLabel + ")");
|
|
101
|
+
i0.ɵɵadvance(5);
|
|
102
|
+
i0.ɵɵtextInterpolate(ctx_r3.OmnibarShortcutLabel);
|
|
103
|
+
} }
|
|
104
|
+
function ShellComponent_Conditional_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
105
|
+
const _r8 = i0.ɵɵgetCurrentView();
|
|
106
|
+
i0.ɵɵelementStart(0, "div", 54)(1, "mj-search-composite", 55, 3);
|
|
107
|
+
i0.ɵɵlistener("ResultSelected", function ShellComponent_Conditional_10_Conditional_1_Template_mj_search_composite_ResultSelected_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnSearchResultSelected($event)); })("SearchSubmitted", function ShellComponent_Conditional_10_Conditional_1_Template_mj_search_composite_SearchSubmitted_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnSearchSubmitted($event)); })("SeeAllRequested", function ShellComponent_Conditional_10_Conditional_1_Template_mj_search_composite_SeeAllRequested_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnSeeAllSearch($event)); })("RecentRecordSelected", function ShellComponent_Conditional_10_Conditional_1_Template_mj_search_composite_RecentRecordSelected_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnSearchResultSelected($event)); })("PromoAccepted", function ShellComponent_Conditional_10_Conditional_1_Template_mj_search_composite_PromoAccepted_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnOmnibarPromoAccepted($event)); })("PromoDismissed", function ShellComponent_Conditional_10_Conditional_1_Template_mj_search_composite_PromoDismissed_1_listener() { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnOmnibarPromoDismissed()); });
|
|
108
|
+
i0.ɵɵelementEnd()();
|
|
109
|
+
i0.ɵɵelementStart(3, "button", 56);
|
|
110
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_10_Conditional_1_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r8); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnHeaderSearchClick()); });
|
|
111
|
+
i0.ɵɵelement(4, "i", 51);
|
|
112
|
+
i0.ɵɵelementEnd();
|
|
113
|
+
} if (rf & 2) {
|
|
114
|
+
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
90
115
|
i0.ɵɵadvance();
|
|
91
|
-
i0.ɵɵproperty("ShowShortcutHint", true)("EnablePreview", ctx_r3.ShowSearchPreview)("EnableRecent", true)("MaxPreviewResults", 8);
|
|
116
|
+
i0.ɵɵproperty("ShowShortcutHint", true)("EnablePreview", ctx_r3.ShowSearchPreview)("EnableRecent", true)("MaxPreviewResults", 8)("ShowPromo", ctx_r3.ShowOmnibarPromo)("PromoText", ctx_r3.OmnibarPromoText);
|
|
117
|
+
i0.ɵɵadvance(2);
|
|
118
|
+
i0.ɵɵattribute("aria-label", "Search everything (" + ctx_r3.OmnibarShortcutLabel + ")");
|
|
119
|
+
} }
|
|
120
|
+
function ShellComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_10_Conditional_0_Template, 6, 2, "button", 49)(1, ShellComponent_Conditional_10_Conditional_1_Template, 5, 7);
|
|
122
|
+
} if (rf & 2) {
|
|
123
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
124
|
+
i0.ɵɵconditional(ctx_r3.UseOmnibar ? 0 : 1);
|
|
92
125
|
} }
|
|
93
126
|
function ShellComponent_Conditional_11_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
94
|
-
i0.ɵɵelementStart(0, "span",
|
|
127
|
+
i0.ɵɵelementStart(0, "span", 59);
|
|
95
128
|
i0.ɵɵtext(1);
|
|
96
129
|
i0.ɵɵelementEnd();
|
|
97
130
|
} if (rf & 2) {
|
|
@@ -100,57 +133,57 @@ function ShellComponent_Conditional_11_Conditional_3_Template(rf, ctx) { if (rf
|
|
|
100
133
|
i0.ɵɵtextInterpolate(ctx_r3.activityRunningCount);
|
|
101
134
|
} }
|
|
102
135
|
function ShellComponent_Conditional_11_Conditional_4_For_8_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
103
|
-
i0.ɵɵelementStart(0, "div",
|
|
136
|
+
i0.ɵɵelementStart(0, "div", 71);
|
|
104
137
|
i0.ɵɵtext(1);
|
|
105
138
|
i0.ɵɵelementEnd();
|
|
106
139
|
} if (rf & 2) {
|
|
107
|
-
const
|
|
140
|
+
const a_r11 = i0.ɵɵnextContext().$implicit;
|
|
108
141
|
i0.ɵɵadvance();
|
|
109
|
-
i0.ɵɵtextInterpolate(
|
|
142
|
+
i0.ɵɵtextInterpolate(a_r11.Detail);
|
|
110
143
|
} }
|
|
111
144
|
function ShellComponent_Conditional_11_Conditional_4_For_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
|
|
112
|
-
i0.ɵɵelementStart(0, "div",
|
|
113
|
-
i0.ɵɵelement(1, "div",
|
|
145
|
+
i0.ɵɵelementStart(0, "div", 72);
|
|
146
|
+
i0.ɵɵelement(1, "div", 73);
|
|
114
147
|
i0.ɵɵelementEnd();
|
|
115
148
|
} if (rf & 2) {
|
|
116
|
-
const
|
|
149
|
+
const a_r11 = i0.ɵɵnextContext().$implicit;
|
|
117
150
|
i0.ɵɵadvance();
|
|
118
|
-
i0.ɵɵstyleProp("width",
|
|
151
|
+
i0.ɵɵstyleProp("width", a_r11.Progress, "%");
|
|
119
152
|
} }
|
|
120
153
|
function ShellComponent_Conditional_11_Conditional_4_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
-
i0.ɵɵelementStart(0, "div",
|
|
122
|
-
i0.ɵɵelement(1, "i",
|
|
123
|
-
i0.ɵɵelementStart(2, "div",
|
|
154
|
+
i0.ɵɵelementStart(0, "div", 67);
|
|
155
|
+
i0.ɵɵelement(1, "i", 68);
|
|
156
|
+
i0.ɵɵelementStart(2, "div", 69)(3, "div", 70);
|
|
124
157
|
i0.ɵɵtext(4);
|
|
125
158
|
i0.ɵɵelementEnd();
|
|
126
|
-
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_11_Conditional_4_For_8_Conditional_5_Template, 2, 1, "div",
|
|
127
|
-
i0.ɵɵconditionalCreate(6, ShellComponent_Conditional_11_Conditional_4_For_8_Conditional_6_Template, 2, 2, "div",
|
|
159
|
+
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_11_Conditional_4_For_8_Conditional_5_Template, 2, 1, "div", 71);
|
|
160
|
+
i0.ɵɵconditionalCreate(6, ShellComponent_Conditional_11_Conditional_4_For_8_Conditional_6_Template, 2, 2, "div", 72);
|
|
128
161
|
i0.ɵɵelementEnd()();
|
|
129
162
|
} if (rf & 2) {
|
|
130
|
-
const
|
|
131
|
-
i0.ɵɵclassProp("is-error",
|
|
163
|
+
const a_r11 = ctx.$implicit;
|
|
164
|
+
i0.ɵɵclassProp("is-error", a_r11.Status === "error");
|
|
132
165
|
i0.ɵɵadvance();
|
|
133
|
-
i0.ɵɵclassMap(
|
|
166
|
+
i0.ɵɵclassMap(a_r11.Status === "running" ? "fa-solid fa-spinner fa-spin" : a_r11.Status === "error" ? "fa-solid fa-circle-exclamation" : "fa-solid fa-circle-check");
|
|
134
167
|
i0.ɵɵadvance(3);
|
|
135
|
-
i0.ɵɵtextInterpolate(
|
|
168
|
+
i0.ɵɵtextInterpolate(a_r11.Label);
|
|
136
169
|
i0.ɵɵadvance();
|
|
137
|
-
i0.ɵɵconditional(
|
|
170
|
+
i0.ɵɵconditional(a_r11.Detail ? 5 : -1);
|
|
138
171
|
i0.ɵɵadvance();
|
|
139
|
-
i0.ɵɵconditional(
|
|
172
|
+
i0.ɵɵconditional(a_r11.Status === "running" && a_r11.Progress != null ? 6 : -1);
|
|
140
173
|
} }
|
|
141
174
|
function ShellComponent_Conditional_11_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
142
|
-
const
|
|
143
|
-
i0.ɵɵelementStart(0, "div",
|
|
144
|
-
i0.ɵɵlistener("click", function ShellComponent_Conditional_11_Conditional_4_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(
|
|
145
|
-
i0.ɵɵelementStart(1, "div",
|
|
175
|
+
const _r10 = i0.ɵɵgetCurrentView();
|
|
176
|
+
i0.ɵɵelementStart(0, "div", 61);
|
|
177
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_11_Conditional_4_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r10); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
178
|
+
i0.ɵɵelementStart(1, "div", 62)(2, "span");
|
|
146
179
|
i0.ɵɵtext(3, "Activity");
|
|
147
180
|
i0.ɵɵelementEnd();
|
|
148
|
-
i0.ɵɵelementStart(4, "button",
|
|
149
|
-
i0.ɵɵlistener("click", function ShellComponent_Conditional_11_Conditional_4_Template_button_click_4_listener() { i0.ɵɵrestoreView(
|
|
150
|
-
i0.ɵɵelement(5, "i",
|
|
181
|
+
i0.ɵɵelementStart(4, "button", 63);
|
|
182
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_11_Conditional_4_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r10); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.clearFinishedActivity()); });
|
|
183
|
+
i0.ɵɵelement(5, "i", 64);
|
|
151
184
|
i0.ɵɵelementEnd()();
|
|
152
|
-
i0.ɵɵelementStart(6, "div",
|
|
153
|
-
i0.ɵɵrepeaterCreate(7, ShellComponent_Conditional_11_Conditional_4_For_8_Template, 7, 7, "div",
|
|
185
|
+
i0.ɵɵelementStart(6, "div", 65);
|
|
186
|
+
i0.ɵɵrepeaterCreate(7, ShellComponent_Conditional_11_Conditional_4_For_8_Template, 7, 7, "div", 66, _forTrack0);
|
|
154
187
|
i0.ɵɵelementEnd()();
|
|
155
188
|
} if (rf & 2) {
|
|
156
189
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
@@ -158,13 +191,13 @@ function ShellComponent_Conditional_11_Conditional_4_Template(rf, ctx) { if (rf
|
|
|
158
191
|
i0.ɵɵrepeater(ctx_r3.activityItems);
|
|
159
192
|
} }
|
|
160
193
|
function ShellComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
161
|
-
const
|
|
162
|
-
i0.ɵɵelementStart(0, "div", 14)(1, "button",
|
|
163
|
-
i0.ɵɵlistener("click", function ShellComponent_Conditional_11_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(
|
|
164
|
-
i0.ɵɵelement(2, "i",
|
|
165
|
-
i0.ɵɵconditionalCreate(3, ShellComponent_Conditional_11_Conditional_3_Template, 2, 1, "span",
|
|
194
|
+
const _r9 = i0.ɵɵgetCurrentView();
|
|
195
|
+
i0.ɵɵelementStart(0, "div", 14)(1, "button", 57);
|
|
196
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_11_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.toggleActivity($event)); });
|
|
197
|
+
i0.ɵɵelement(2, "i", 58);
|
|
198
|
+
i0.ɵɵconditionalCreate(3, ShellComponent_Conditional_11_Conditional_3_Template, 2, 1, "span", 59);
|
|
166
199
|
i0.ɵɵelementEnd();
|
|
167
|
-
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_11_Conditional_4_Template, 9, 0, "div",
|
|
200
|
+
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_11_Conditional_4_Template, 9, 0, "div", 60);
|
|
168
201
|
i0.ɵɵelementEnd();
|
|
169
202
|
} if (rf & 2) {
|
|
170
203
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -175,47 +208,59 @@ function ShellComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
|
175
208
|
i0.ɵɵadvance();
|
|
176
209
|
i0.ɵɵconditional(ctx_r3.activityOpen ? 4 : -1);
|
|
177
210
|
} }
|
|
178
|
-
function
|
|
179
|
-
i0.ɵɵelementStart(0, "span",
|
|
211
|
+
function ShellComponent_Conditional_12_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
212
|
+
i0.ɵɵelementStart(0, "span", 76);
|
|
180
213
|
i0.ɵɵtext(1);
|
|
181
214
|
i0.ɵɵelementEnd();
|
|
182
215
|
} if (rf & 2) {
|
|
183
|
-
const ctx_r3 = i0.ɵɵnextContext();
|
|
216
|
+
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
184
217
|
i0.ɵɵadvance();
|
|
185
218
|
i0.ɵɵtextInterpolate1(" ", ctx_r3.unreadNotificationCount > 99 ? "99+" : ctx_r3.unreadNotificationCount, " ");
|
|
186
219
|
} }
|
|
187
|
-
function
|
|
188
|
-
const
|
|
189
|
-
i0.ɵɵelementStart(0, "button",
|
|
190
|
-
i0.ɵɵlistener("click", function
|
|
220
|
+
function ShellComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
221
|
+
const _r12 = i0.ɵɵgetCurrentView();
|
|
222
|
+
i0.ɵɵelementStart(0, "button", 74);
|
|
223
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_12_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r12); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.showNotifications()); });
|
|
224
|
+
i0.ɵɵelement(1, "i", 75);
|
|
225
|
+
i0.ɵɵconditionalCreate(2, ShellComponent_Conditional_12_Conditional_2_Template, 2, 1, "span", 76);
|
|
226
|
+
i0.ɵɵelementEnd();
|
|
227
|
+
} if (rf & 2) {
|
|
228
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
229
|
+
i0.ɵɵadvance(2);
|
|
230
|
+
i0.ɵɵconditional(ctx_r3.unreadNotificationCount > 0 ? 2 : -1);
|
|
231
|
+
} }
|
|
232
|
+
function ShellComponent_Conditional_13_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
233
|
+
const _r13 = i0.ɵɵgetCurrentView();
|
|
234
|
+
i0.ɵɵelementStart(0, "button", 46);
|
|
235
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_13_For_2_Template_button_click_0_listener($event) { const app_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppClick(app_r14, $event)); })("dblclick", function ShellComponent_Conditional_13_For_2_Template_button_dblclick_0_listener($event) { const app_r14 = i0.ɵɵrestoreView(_r13).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.onNavBarAppDblClick(app_r14, $event)); });
|
|
191
236
|
i0.ɵɵelement(1, "i");
|
|
192
237
|
i0.ɵɵelementEnd();
|
|
193
238
|
} if (rf & 2) {
|
|
194
|
-
const
|
|
239
|
+
const app_r14 = ctx.$implicit;
|
|
195
240
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
196
|
-
i0.ɵɵstyleProp("--app-color",
|
|
197
|
-
i0.ɵɵclassProp("active", ctx_r3.IsActiveApp(
|
|
198
|
-
i0.ɵɵproperty("title",
|
|
241
|
+
i0.ɵɵstyleProp("--app-color", app_r14.GetColor());
|
|
242
|
+
i0.ɵɵclassProp("active", ctx_r3.IsActiveApp(app_r14));
|
|
243
|
+
i0.ɵɵproperty("title", app_r14.Name);
|
|
199
244
|
i0.ɵɵadvance();
|
|
200
|
-
i0.ɵɵclassMap(
|
|
245
|
+
i0.ɵɵclassMap(app_r14.Icon);
|
|
201
246
|
} }
|
|
202
|
-
function
|
|
203
|
-
i0.ɵɵelementStart(0, "div",
|
|
204
|
-
i0.ɵɵrepeaterCreate(1,
|
|
247
|
+
function ShellComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
248
|
+
i0.ɵɵelementStart(0, "div", 16);
|
|
249
|
+
i0.ɵɵrepeaterCreate(1, ShellComponent_Conditional_13_For_2_Template, 2, 7, "button", 45, i0.ɵɵrepeaterTrackByIdentity);
|
|
205
250
|
i0.ɵɵelementEnd();
|
|
206
251
|
} if (rf & 2) {
|
|
207
252
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
208
253
|
i0.ɵɵadvance();
|
|
209
254
|
i0.ɵɵrepeater(ctx_r3.leftOfUserMenuApps);
|
|
210
255
|
} }
|
|
211
|
-
function
|
|
212
|
-
i0.ɵɵelement(0, "img",
|
|
256
|
+
function ShellComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
257
|
+
i0.ɵɵelement(0, "img", 19);
|
|
213
258
|
} if (rf & 2) {
|
|
214
259
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
215
260
|
i0.ɵɵproperty("src", ctx_r3.userImageURL, i0.ɵɵsanitizeUrl);
|
|
216
261
|
} }
|
|
217
|
-
function
|
|
218
|
-
i0.ɵɵelementStart(0, "div",
|
|
262
|
+
function ShellComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
263
|
+
i0.ɵɵelementStart(0, "div", 20);
|
|
219
264
|
i0.ɵɵelement(1, "i");
|
|
220
265
|
i0.ɵɵelementEnd();
|
|
221
266
|
} if (rf & 2) {
|
|
@@ -223,162 +268,162 @@ function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
|
223
268
|
i0.ɵɵadvance();
|
|
224
269
|
i0.ɵɵclassMap(ctx_r3.userIconClass || "fa-solid fa-user");
|
|
225
270
|
} }
|
|
226
|
-
function
|
|
227
|
-
i0.ɵɵelementStart(0, "span",
|
|
271
|
+
function ShellComponent_Conditional_18_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
272
|
+
i0.ɵɵelementStart(0, "span", 81);
|
|
228
273
|
i0.ɵɵtext(1);
|
|
229
274
|
i0.ɵɵelementEnd();
|
|
230
275
|
} if (rf & 2) {
|
|
231
|
-
let
|
|
276
|
+
let tmp_6_0;
|
|
232
277
|
const ctx_r3 = i0.ɵɵnextContext(3);
|
|
233
278
|
i0.ɵɵadvance();
|
|
234
|
-
i0.ɵɵtextInterpolate1(" ", (
|
|
279
|
+
i0.ɵɵtextInterpolate1(" ", (tmp_6_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_6_0.email, " ");
|
|
235
280
|
} }
|
|
236
|
-
function
|
|
237
|
-
i0.ɵɵelementStart(0, "span",
|
|
281
|
+
function ShellComponent_Conditional_18_Conditional_1_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
282
|
+
i0.ɵɵelementStart(0, "span", 82);
|
|
238
283
|
i0.ɵɵtext(1);
|
|
239
284
|
i0.ɵɵelementEnd();
|
|
240
285
|
} if (rf & 2) {
|
|
241
|
-
let
|
|
286
|
+
let tmp_6_0;
|
|
242
287
|
const ctx_r3 = i0.ɵɵnextContext(3);
|
|
243
288
|
i0.ɵɵadvance();
|
|
244
|
-
i0.ɵɵtextInterpolate((
|
|
289
|
+
i0.ɵɵtextInterpolate((tmp_6_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_6_0.subtitle);
|
|
245
290
|
} }
|
|
246
|
-
function
|
|
247
|
-
i0.ɵɵelementStart(0, "div",
|
|
291
|
+
function ShellComponent_Conditional_18_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
292
|
+
i0.ɵɵelementStart(0, "div", 78)(1, "div", 79)(2, "span", 80);
|
|
248
293
|
i0.ɵɵtext(3);
|
|
249
294
|
i0.ɵɵelementEnd();
|
|
250
|
-
i0.ɵɵconditionalCreate(4,
|
|
251
|
-
i0.ɵɵconditionalCreate(5,
|
|
295
|
+
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_18_Conditional_1_Conditional_4_Template, 2, 1, "span", 81);
|
|
296
|
+
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_18_Conditional_1_Conditional_5_Template, 2, 1, "span", 82);
|
|
252
297
|
i0.ɵɵelementEnd()();
|
|
253
|
-
i0.ɵɵelement(6, "div",
|
|
298
|
+
i0.ɵɵelement(6, "div", 83);
|
|
254
299
|
} if (rf & 2) {
|
|
255
|
-
let tmp_4_0;
|
|
256
300
|
let tmp_5_0;
|
|
257
301
|
let tmp_6_0;
|
|
302
|
+
let tmp_7_0;
|
|
258
303
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
259
304
|
i0.ɵɵadvance(3);
|
|
260
|
-
i0.ɵɵtextInterpolate(((
|
|
305
|
+
i0.ɵɵtextInterpolate(((tmp_5_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_5_0.name) || ctx_r3.userName);
|
|
261
306
|
i0.ɵɵadvance();
|
|
262
|
-
i0.ɵɵconditional(((
|
|
307
|
+
i0.ɵɵconditional(((tmp_6_0 = ctx_r3.getUserMenuOptions()) == null ? null : tmp_6_0.showUserEmail) && ((tmp_6_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_6_0.email) ? 4 : -1);
|
|
263
308
|
i0.ɵɵadvance();
|
|
264
|
-
i0.ɵɵconditional(((
|
|
309
|
+
i0.ɵɵconditional(((tmp_7_0 = ctx_r3.getUserDisplayInfo()) == null ? null : tmp_7_0.subtitle) ? 5 : -1);
|
|
265
310
|
} }
|
|
266
|
-
function
|
|
267
|
-
i0.ɵɵelement(0, "div",
|
|
311
|
+
function ShellComponent_Conditional_18_For_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
312
|
+
i0.ɵɵelement(0, "div", 83);
|
|
268
313
|
} }
|
|
269
|
-
function
|
|
270
|
-
const
|
|
271
|
-
i0.ɵɵelementStart(0, "div",
|
|
272
|
-
i0.ɵɵlistener("click", function
|
|
314
|
+
function ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
315
|
+
const _r15 = i0.ɵɵgetCurrentView();
|
|
316
|
+
i0.ɵɵelementStart(0, "div", 86);
|
|
317
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_0_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r15); const item_r16 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r3.onUserMenuItemClick(item_r16.id)); });
|
|
273
318
|
i0.ɵɵelement(1, "i");
|
|
274
|
-
i0.ɵɵelementStart(2, "span",
|
|
319
|
+
i0.ɵɵelementStart(2, "span", 87);
|
|
275
320
|
i0.ɵɵtext(3);
|
|
276
321
|
i0.ɵɵelementEnd();
|
|
277
|
-
i0.ɵɵelementStart(4, "div",
|
|
278
|
-
i0.ɵɵelement(6, "i",
|
|
322
|
+
i0.ɵɵelementStart(4, "div", 88)(5, "div", 89);
|
|
323
|
+
i0.ɵɵelement(6, "i", 90);
|
|
279
324
|
i0.ɵɵelementEnd()()();
|
|
280
325
|
} if (rf & 2) {
|
|
281
|
-
const
|
|
326
|
+
const item_r16 = i0.ɵɵnextContext();
|
|
282
327
|
const ctx_r3 = i0.ɵɵnextContext(4);
|
|
283
|
-
i0.ɵɵproperty("title",
|
|
328
|
+
i0.ɵɵproperty("title", item_r16.tooltip || "");
|
|
284
329
|
i0.ɵɵadvance();
|
|
285
|
-
i0.ɵɵclassMap(
|
|
330
|
+
i0.ɵɵclassMap(item_r16.icon);
|
|
286
331
|
i0.ɵɵadvance(2);
|
|
287
|
-
i0.ɵɵtextInterpolate(
|
|
332
|
+
i0.ɵɵtextInterpolate(item_r16.label);
|
|
288
333
|
i0.ɵɵadvance();
|
|
289
334
|
i0.ɵɵclassProp("dark", ctx_r3.IsDarkMode);
|
|
290
335
|
i0.ɵɵadvance(2);
|
|
291
336
|
i0.ɵɵclassMap(ctx_r3.IsDarkMode ? "fa-solid fa-moon" : "fa-solid fa-sun");
|
|
292
337
|
} }
|
|
293
|
-
function
|
|
294
|
-
i0.ɵɵelementStart(0, "span",
|
|
338
|
+
function ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
339
|
+
i0.ɵɵelementStart(0, "span", 92);
|
|
295
340
|
i0.ɵɵtext(1);
|
|
296
341
|
i0.ɵɵelementEnd();
|
|
297
342
|
} if (rf & 2) {
|
|
298
|
-
const
|
|
343
|
+
const item_r16 = i0.ɵɵnextContext(2);
|
|
299
344
|
i0.ɵɵadvance();
|
|
300
|
-
i0.ɵɵtextInterpolate(
|
|
345
|
+
i0.ɵɵtextInterpolate(item_r16.shortcut);
|
|
301
346
|
} }
|
|
302
|
-
function
|
|
303
|
-
const
|
|
304
|
-
i0.ɵɵelementStart(0, "div",
|
|
305
|
-
i0.ɵɵlistener("click", function
|
|
347
|
+
function ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
348
|
+
const _r17 = i0.ɵɵgetCurrentView();
|
|
349
|
+
i0.ɵɵelementStart(0, "div", 91);
|
|
350
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_1_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r17); const item_r16 = i0.ɵɵnextContext(); const ctx_r3 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(item_r16.enabled && ctx_r3.onUserMenuItemClick(item_r16.id)); });
|
|
306
351
|
i0.ɵɵelement(1, "i");
|
|
307
|
-
i0.ɵɵelementStart(2, "span",
|
|
352
|
+
i0.ɵɵelementStart(2, "span", 87);
|
|
308
353
|
i0.ɵɵtext(3);
|
|
309
354
|
i0.ɵɵelementEnd();
|
|
310
|
-
i0.ɵɵconditionalCreate(4,
|
|
355
|
+
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_1_Conditional_4_Template, 2, 1, "span", 92);
|
|
311
356
|
i0.ɵɵelementEnd();
|
|
312
357
|
} if (rf & 2) {
|
|
313
|
-
const
|
|
314
|
-
i0.ɵɵstyleProp("color",
|
|
315
|
-
i0.ɵɵclassProp("disabled", !
|
|
316
|
-
i0.ɵɵproperty("title",
|
|
358
|
+
const item_r16 = i0.ɵɵnextContext();
|
|
359
|
+
i0.ɵɵstyleProp("color", item_r16.color || null);
|
|
360
|
+
i0.ɵɵclassProp("disabled", !item_r16.enabled)("danger", item_r16.cssClass === "danger");
|
|
361
|
+
i0.ɵɵproperty("title", item_r16.tooltip || "");
|
|
317
362
|
i0.ɵɵadvance();
|
|
318
|
-
i0.ɵɵclassMap(
|
|
363
|
+
i0.ɵɵclassMap(item_r16.icon);
|
|
319
364
|
i0.ɵɵadvance(2);
|
|
320
|
-
i0.ɵɵtextInterpolate(
|
|
365
|
+
i0.ɵɵtextInterpolate(item_r16.label);
|
|
321
366
|
i0.ɵɵadvance();
|
|
322
|
-
i0.ɵɵconditional(
|
|
367
|
+
i0.ɵɵconditional(item_r16.shortcut ? 4 : -1);
|
|
323
368
|
} }
|
|
324
|
-
function
|
|
325
|
-
i0.ɵɵconditionalCreate(0,
|
|
369
|
+
function ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
370
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_0_Template, 7, 8, "div", 84)(1, ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Conditional_1_Template, 5, 11, "div", 85);
|
|
326
371
|
} if (rf & 2) {
|
|
327
372
|
i0.ɵɵconditional(ctx.id === "toggle-theme" ? 0 : 1);
|
|
328
373
|
} }
|
|
329
|
-
function
|
|
330
|
-
i0.ɵɵconditionalCreate(0,
|
|
374
|
+
function ShellComponent_Conditional_18_For_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
375
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_18_For_3_Conditional_1_Conditional_0_Template, 2, 1);
|
|
331
376
|
} if (rf & 2) {
|
|
332
|
-
let
|
|
333
|
-
const
|
|
377
|
+
let tmp_15_0;
|
|
378
|
+
const element_r18 = i0.ɵɵnextContext().$implicit;
|
|
334
379
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
335
|
-
i0.ɵɵconditional((
|
|
380
|
+
i0.ɵɵconditional((tmp_15_0 = ctx_r3.asMenuItem(element_r18)) ? 0 : -1, tmp_15_0);
|
|
336
381
|
} }
|
|
337
|
-
function
|
|
338
|
-
i0.ɵɵconditionalCreate(0,
|
|
339
|
-
i0.ɵɵconditionalCreate(1,
|
|
382
|
+
function ShellComponent_Conditional_18_For_3_Template(rf, ctx) { if (rf & 1) {
|
|
383
|
+
i0.ɵɵconditionalCreate(0, ShellComponent_Conditional_18_For_3_Conditional_0_Template, 1, 0, "div", 83);
|
|
384
|
+
i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_18_For_3_Conditional_1_Template, 1, 1);
|
|
340
385
|
} if (rf & 2) {
|
|
341
|
-
const
|
|
386
|
+
const element_r18 = ctx.$implicit;
|
|
342
387
|
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
343
|
-
i0.ɵɵconditional(ctx_r3.isMenuDivider(
|
|
388
|
+
i0.ɵɵconditional(ctx_r3.isMenuDivider(element_r18) ? 0 : -1);
|
|
344
389
|
i0.ɵɵadvance();
|
|
345
|
-
i0.ɵɵconditional(!ctx_r3.isMenuDivider(
|
|
390
|
+
i0.ɵɵconditional(!ctx_r3.isMenuDivider(element_r18) ? 1 : -1);
|
|
346
391
|
} }
|
|
347
|
-
function
|
|
348
|
-
i0.ɵɵelementStart(0, "div",
|
|
349
|
-
i0.ɵɵconditionalCreate(1,
|
|
350
|
-
i0.ɵɵrepeaterCreate(2,
|
|
392
|
+
function ShellComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
393
|
+
i0.ɵɵelementStart(0, "div", 77);
|
|
394
|
+
i0.ɵɵconditionalCreate(1, ShellComponent_Conditional_18_Conditional_1_Template, 7, 3);
|
|
395
|
+
i0.ɵɵrepeaterCreate(2, ShellComponent_Conditional_18_For_3_Template, 2, 2, null, null, i0.ɵɵrepeaterTrackByIdentity);
|
|
351
396
|
i0.ɵɵelementEnd();
|
|
352
397
|
} if (rf & 2) {
|
|
353
|
-
let tmp_3_0;
|
|
354
398
|
let tmp_4_0;
|
|
355
399
|
let tmp_5_0;
|
|
400
|
+
let tmp_6_0;
|
|
356
401
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
357
|
-
i0.ɵɵclassProp("menu-fade", ((
|
|
402
|
+
i0.ɵɵclassProp("menu-fade", ((tmp_4_0 = ctx_r3.getUserMenuOptions()) == null ? null : tmp_4_0.animationStyle) === "fade")("menu-slide", ((tmp_5_0 = ctx_r3.getUserMenuOptions()) == null ? null : tmp_5_0.animationStyle) === "slide");
|
|
358
403
|
i0.ɵɵadvance();
|
|
359
|
-
i0.ɵɵconditional(((
|
|
404
|
+
i0.ɵɵconditional(((tmp_6_0 = ctx_r3.getUserMenuOptions()) == null ? null : tmp_6_0.showUserName) ? 1 : -1);
|
|
360
405
|
i0.ɵɵadvance();
|
|
361
406
|
i0.ɵɵrepeater(ctx_r3.userMenuElements);
|
|
362
407
|
} }
|
|
363
|
-
function
|
|
364
|
-
const
|
|
365
|
-
i0.ɵɵelementStart(0, "div",
|
|
366
|
-
i0.ɵɵlistener("click", function
|
|
408
|
+
function ShellComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
409
|
+
const _r19 = i0.ɵɵgetCurrentView();
|
|
410
|
+
i0.ɵɵelementStart(0, "div", 93);
|
|
411
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_19_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r19); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeSearch()); });
|
|
367
412
|
i0.ɵɵelementEnd();
|
|
368
413
|
} }
|
|
369
|
-
function
|
|
370
|
-
const
|
|
371
|
-
i0.ɵɵelementStart(0, "div",
|
|
372
|
-
i0.ɵɵlistener("click", function
|
|
414
|
+
function ShellComponent_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
415
|
+
const _r20 = i0.ɵɵgetCurrentView();
|
|
416
|
+
i0.ɵɵelementStart(0, "div", 94);
|
|
417
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_27_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.closeMobileNav()); });
|
|
373
418
|
i0.ɵɵelementEnd();
|
|
374
419
|
} }
|
|
375
|
-
function
|
|
376
|
-
const
|
|
377
|
-
i0.ɵɵelementStart(0, "div",
|
|
420
|
+
function ShellComponent_Conditional_34_Template(rf, ctx) { if (rf & 1) {
|
|
421
|
+
const _r21 = i0.ɵɵgetCurrentView();
|
|
422
|
+
i0.ɵɵelementStart(0, "div", 34)(1, "div", 95);
|
|
378
423
|
i0.ɵɵtext(2);
|
|
379
424
|
i0.ɵɵelementEnd();
|
|
380
|
-
i0.ɵɵelementStart(3, "mj-app-nav",
|
|
381
|
-
i0.ɵɵlistener("navItemClick", function
|
|
425
|
+
i0.ɵɵelementStart(3, "mj-app-nav", 96);
|
|
426
|
+
i0.ɵɵlistener("navItemClick", function ShellComponent_Conditional_34_Template_mj_app_nav_navItemClick_3_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemClick($event)); })("navItemDismiss", function ShellComponent_Conditional_34_Template_mj_app_nav_navItemDismiss_3_listener($event) { i0.ɵɵrestoreView(_r21); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.onNavItemDismiss($event)); });
|
|
382
427
|
i0.ɵɵelementEnd()();
|
|
383
428
|
} if (rf & 2) {
|
|
384
429
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -387,32 +432,47 @@ function ShellComponent_Conditional_36_Template(rf, ctx) { if (rf & 1) {
|
|
|
387
432
|
i0.ɵɵadvance();
|
|
388
433
|
i0.ɵɵproperty("app", ctx_r3.activeApp);
|
|
389
434
|
} }
|
|
390
|
-
function
|
|
391
|
-
i0.ɵɵelementStart(0, "span",
|
|
435
|
+
function ShellComponent_Conditional_40_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
436
|
+
i0.ɵɵelementStart(0, "span", 98);
|
|
392
437
|
i0.ɵɵtext(1);
|
|
393
438
|
i0.ɵɵelementEnd();
|
|
394
439
|
} if (rf & 2) {
|
|
395
|
-
const ctx_r3 = i0.ɵɵnextContext();
|
|
440
|
+
const ctx_r3 = i0.ɵɵnextContext(2);
|
|
396
441
|
i0.ɵɵadvance();
|
|
397
442
|
i0.ɵɵtextInterpolate1(" ", ctx_r3.unreadNotificationCount > 99 ? "99+" : ctx_r3.unreadNotificationCount, " ");
|
|
398
443
|
} }
|
|
399
|
-
function
|
|
400
|
-
const
|
|
401
|
-
i0.ɵɵelementStart(0, "
|
|
402
|
-
i0.ɵɵ
|
|
444
|
+
function ShellComponent_Conditional_40_Template(rf, ctx) { if (rf & 1) {
|
|
445
|
+
const _r22 = i0.ɵɵgetCurrentView();
|
|
446
|
+
i0.ɵɵelementStart(0, "button", 97);
|
|
447
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_40_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r3 = i0.ɵɵnextContext(); ctx_r3.showNotifications(); return i0.ɵɵresetView(ctx_r3.closeMobileNav()); });
|
|
448
|
+
i0.ɵɵelement(1, "i", 75);
|
|
449
|
+
i0.ɵɵelementStart(2, "span");
|
|
450
|
+
i0.ɵɵtext(3, "Notifications");
|
|
451
|
+
i0.ɵɵelementEnd();
|
|
452
|
+
i0.ɵɵconditionalCreate(4, ShellComponent_Conditional_40_Conditional_4_Template, 2, 1, "span", 98);
|
|
453
|
+
i0.ɵɵelementEnd();
|
|
454
|
+
} if (rf & 2) {
|
|
455
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
456
|
+
i0.ɵɵadvance(4);
|
|
457
|
+
i0.ɵɵconditional(ctx_r3.unreadNotificationCount > 0 ? 4 : -1);
|
|
458
|
+
} }
|
|
459
|
+
function ShellComponent_Conditional_42_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
460
|
+
const _r23 = i0.ɵɵgetCurrentView();
|
|
461
|
+
i0.ɵɵelementStart(0, "div", 100)(1, "p", 102);
|
|
462
|
+
i0.ɵɵelement(2, "i", 103);
|
|
403
463
|
i0.ɵɵtext(3, " Taking longer than expected ");
|
|
404
464
|
i0.ɵɵelementEnd();
|
|
405
|
-
i0.ɵɵelementStart(4, "p",
|
|
465
|
+
i0.ɵɵelementStart(4, "p", 104);
|
|
406
466
|
i0.ɵɵtext(5, " This can happen after updates or due to cached data issues. ");
|
|
407
467
|
i0.ɵɵelementEnd();
|
|
408
|
-
i0.ɵɵelementStart(6, "button",
|
|
409
|
-
i0.ɵɵlistener("click", function
|
|
410
|
-
i0.ɵɵelement(7, "i",
|
|
468
|
+
i0.ɵɵelementStart(6, "button", 105);
|
|
469
|
+
i0.ɵɵlistener("click", function ShellComponent_Conditional_42_Conditional_2_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r23); const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.ResetApplication()); });
|
|
470
|
+
i0.ɵɵelement(7, "i", 106);
|
|
411
471
|
i0.ɵɵtext(8, " Reset ");
|
|
412
472
|
i0.ɵɵelementEnd()();
|
|
413
473
|
} }
|
|
414
|
-
function
|
|
415
|
-
i0.ɵɵelementStart(0, "div",
|
|
474
|
+
function ShellComponent_Conditional_42_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
475
|
+
i0.ɵɵelementStart(0, "div", 101);
|
|
416
476
|
i0.ɵɵtext(1);
|
|
417
477
|
i0.ɵɵelementEnd();
|
|
418
478
|
} if (rf & 2) {
|
|
@@ -420,10 +480,10 @@ function ShellComponent_Conditional_48_Conditional_3_Template(rf, ctx) { if (rf
|
|
|
420
480
|
i0.ɵɵadvance();
|
|
421
481
|
i0.ɵɵtextInterpolate1("MemberJunction \u00B7 v", ctx_r3.MJVersion);
|
|
422
482
|
} }
|
|
423
|
-
function
|
|
424
|
-
i0.ɵɵelementStart(0, "div",
|
|
425
|
-
i0.ɵɵelement(1, "mj-loading",
|
|
426
|
-
i0.ɵɵconditionalCreate(2,
|
|
483
|
+
function ShellComponent_Conditional_42_Template(rf, ctx) { if (rf & 1) {
|
|
484
|
+
i0.ɵɵelementStart(0, "div", 39);
|
|
485
|
+
i0.ɵɵelement(1, "mj-loading", 99);
|
|
486
|
+
i0.ɵɵconditionalCreate(2, ShellComponent_Conditional_42_Conditional_2_Template, 9, 0, "div", 100)(3, ShellComponent_Conditional_42_Conditional_3_Template, 2, 1, "div", 101);
|
|
427
487
|
i0.ɵɵelementEnd();
|
|
428
488
|
} if (rf & 2) {
|
|
429
489
|
const ctx_r3 = i0.ɵɵnextContext();
|
|
@@ -432,10 +492,21 @@ function ShellComponent_Conditional_48_Template(rf, ctx) { if (rf & 1) {
|
|
|
432
492
|
i0.ɵɵadvance();
|
|
433
493
|
i0.ɵɵconditional(ctx_r3.ShowResetOption ? 2 : 3);
|
|
434
494
|
} }
|
|
435
|
-
function
|
|
436
|
-
i0.ɵɵ
|
|
437
|
-
i0.ɵɵ
|
|
438
|
-
i0.ɵɵ
|
|
495
|
+
function ShellComponent_Conditional_48_Template(rf, ctx) { if (rf & 1) {
|
|
496
|
+
const _r24 = i0.ɵɵgetCurrentView();
|
|
497
|
+
i0.ɵɵelementStart(0, "mj-search-overlay", 107);
|
|
498
|
+
i0.ɵɵtwoWayListener("IsOpenChange", function ShellComponent_Conditional_48_Template_mj_search_overlay_IsOpenChange_0_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r3 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r3.LegacySearchOpen, $event) || (ctx_r3.LegacySearchOpen = $event); return i0.ɵɵresetView($event); });
|
|
499
|
+
i0.ɵɵlistener("ResultSelected", function ShellComponent_Conditional_48_Template_mj_search_overlay_ResultSelected_0_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnOverlayResultSelected($event)); })("SeeAllRequested", function ShellComponent_Conditional_48_Template_mj_search_overlay_SeeAllRequested_0_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnOverlaySeeAll($event)); })("PromoAccepted", function ShellComponent_Conditional_48_Template_mj_search_overlay_PromoAccepted_0_listener($event) { i0.ɵɵrestoreView(_r24); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnOmnibarPromoAccepted($event)); })("PromoDismissed", function ShellComponent_Conditional_48_Template_mj_search_overlay_PromoDismissed_0_listener() { i0.ɵɵrestoreView(_r24); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnOmnibarPromoDismissed()); });
|
|
500
|
+
i0.ɵɵelementEnd();
|
|
501
|
+
} if (rf & 2) {
|
|
502
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
503
|
+
i0.ɵɵtwoWayProperty("IsOpen", ctx_r3.LegacySearchOpen);
|
|
504
|
+
i0.ɵɵproperty("EnableGlobalShortcut", false)("ShowPromo", ctx_r3.ShowOmnibarPromo)("PromoText", ctx_r3.OmnibarPromoText);
|
|
505
|
+
} }
|
|
506
|
+
function ShellComponent_Conditional_49_Template(rf, ctx) { if (rf & 1) {
|
|
507
|
+
i0.ɵɵelementStart(0, "div", 44)(1, "div", 108);
|
|
508
|
+
i0.ɵɵelement(2, "mj-loading", 109);
|
|
509
|
+
i0.ɵɵelementStart(3, "span", 110);
|
|
439
510
|
i0.ɵɵtext(4);
|
|
440
511
|
i0.ɵɵelementEnd()()();
|
|
441
512
|
} if (rf & 2) {
|
|
@@ -445,14 +516,6 @@ function ShellComponent_Conditional_52_Template(rf, ctx) { if (rf & 1) {
|
|
|
445
516
|
i0.ɵɵadvance(2);
|
|
446
517
|
i0.ɵɵtextInterpolate(ctx_r3.PinProgressText);
|
|
447
518
|
} }
|
|
448
|
-
/**
|
|
449
|
-
* Main shell component for the new Explorer UX.
|
|
450
|
-
*
|
|
451
|
-
* Provides:
|
|
452
|
-
* - App-centric header with app switcher and nav items
|
|
453
|
-
* - Golden Layout-based tab container
|
|
454
|
-
* - Unified workspace state management
|
|
455
|
-
*/
|
|
456
519
|
export class ShellComponent extends BaseAngularComponent {
|
|
457
520
|
appManager;
|
|
458
521
|
workspaceManager;
|
|
@@ -539,14 +602,127 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
539
602
|
searchableEntities = [];
|
|
540
603
|
selectedEntity = null;
|
|
541
604
|
searchInput;
|
|
542
|
-
//
|
|
543
|
-
|
|
544
|
-
//
|
|
605
|
+
// Legacy universal search overlay (omnibar-off MOBILE path) — opened by the
|
|
606
|
+
// mobile search icon or Ctrl/Cmd+K when the inline composite isn't visible.
|
|
607
|
+
// Desktop omnibar-off uses the inline header composite instead.
|
|
608
|
+
LegacySearchOpen = false;
|
|
609
|
+
// Instance configuration feature flags — all resolved through the single
|
|
610
|
+
// memoized `chromeFlags` accessor below (see ShellChromeFlags) so Angular's
|
|
611
|
+
// change detection reads a cached field instead of hitting the engine per pass.
|
|
612
|
+
_chromeFlags = null;
|
|
613
|
+
/**
|
|
614
|
+
* Resolve the instance-config chrome flags once and cache them. Computed live
|
|
615
|
+
* from the fail-open defaults until InstanceConfigEngine has loaded, then frozen
|
|
616
|
+
* on the first post-load read — so the pre-load defaults are never cached over
|
|
617
|
+
* the real values, and every steady-state read is a plain field access.
|
|
618
|
+
*/
|
|
619
|
+
get chromeFlags() {
|
|
620
|
+
if (this._chromeFlags) {
|
|
621
|
+
return this._chromeFlags;
|
|
622
|
+
}
|
|
623
|
+
const engine = InstanceConfigEngine.Instance;
|
|
624
|
+
const flags = {
|
|
625
|
+
searchBar: engine.GetBoolean('Shell.SearchBar.Enabled', true),
|
|
626
|
+
searchPreview: engine.GetBoolean('Shell.SearchBar.EnablePreview', true),
|
|
627
|
+
notifications: engine.GetBoolean('Shell.Notifications.Enabled', true),
|
|
628
|
+
appSwitcher: engine.GetBoolean('Shell.AppSwitcher.Enabled', true),
|
|
629
|
+
appNav: engine.GetBoolean('Shell.AppNav.Enabled', true),
|
|
630
|
+
};
|
|
631
|
+
if (engine.Loaded) {
|
|
632
|
+
this._chromeFlags = flags;
|
|
633
|
+
}
|
|
634
|
+
return flags;
|
|
635
|
+
}
|
|
545
636
|
get ShowSearchBar() {
|
|
546
|
-
return
|
|
637
|
+
return this.chromeFlags.searchBar;
|
|
638
|
+
}
|
|
639
|
+
/** Instance Config gate for the notification bell + unread badge (desktop and mobile). */
|
|
640
|
+
get ShowNotifications() {
|
|
641
|
+
return this.chromeFlags.notifications;
|
|
642
|
+
}
|
|
643
|
+
/** Instance Config gate for the app switcher (also the add/configure-apps entry point). */
|
|
644
|
+
get ShowAppSwitcher() {
|
|
645
|
+
return this.chromeFlags.appSwitcher;
|
|
646
|
+
}
|
|
647
|
+
/** Instance Config gate for the app navigation strip (desktop and the mobile drawer). */
|
|
648
|
+
get ShowAppNav() {
|
|
649
|
+
return this.chromeFlags.appNav;
|
|
547
650
|
}
|
|
548
651
|
get ShowSearchPreview() {
|
|
549
|
-
return
|
|
652
|
+
return this.chromeFlags.searchPreview;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Two-layer gate for the unified Ctrl+K command palette (omnibar):
|
|
656
|
+
* the 'Shell.Omnibar.Enabled' Instance Config row is the master AVAILABILITY
|
|
657
|
+
* switch (default TRUE; false = legacy trio for everyone), and each user
|
|
658
|
+
* opts in personally via My Profile → Command Palette (a UserInfoEngine
|
|
659
|
+
* setting, so the choice follows them across devices). ON = the header shows
|
|
660
|
+
* the palette affordance and Ctrl+K / Ctrl+/ open the palette; OFF = the
|
|
661
|
+
* legacy trio (search composite + app command palette + search popup) behaves
|
|
662
|
+
* exactly as before. Both reads are synchronous cache hits.
|
|
663
|
+
*/
|
|
664
|
+
get UseOmnibar() {
|
|
665
|
+
return IsOmnibarEnabledForUser();
|
|
666
|
+
}
|
|
667
|
+
/** Platform-correct summon-shortcut label ('⌘K' on Mac, 'Ctrl+K' elsewhere). */
|
|
668
|
+
get OmnibarShortcutLabel() {
|
|
669
|
+
return GetOmnibarShortcutLabel();
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Whether the legacy search surfaces advertise the omnibar: the instance makes
|
|
673
|
+
* it available, the user hasn't opted in yet, and they haven't dismissed the
|
|
674
|
+
* promo. Fail-closed (never advertise during boot / permission constraints).
|
|
675
|
+
*/
|
|
676
|
+
get ShowOmnibarPromo() {
|
|
677
|
+
try {
|
|
678
|
+
return IsOmnibarAvailable()
|
|
679
|
+
&& !IsOmnibarEnabledForUser()
|
|
680
|
+
&& UserInfoEngine.Instance.GetSetting(OMNIBAR_PROMO_DISMISSED_KEY) !== 'true';
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
/** Promo copy shown in the legacy search surfaces. */
|
|
687
|
+
OmnibarPromoText = 'Try the new command palette — search, jump to records, switch apps, and message agents from one box.';
|
|
688
|
+
/**
|
|
689
|
+
* Promo accepted: opt the user in (same UserInfoEngine setting as the My
|
|
690
|
+
* Profile toggle, so it follows them across devices), then open the palette
|
|
691
|
+
* pre-seeded with whatever they were just searching — same query, new
|
|
692
|
+
* surface, immediate demonstration.
|
|
693
|
+
*/
|
|
694
|
+
OnOmnibarPromoAccepted(query) {
|
|
695
|
+
// Demonstration first, persistence second: close the legacy surface and open
|
|
696
|
+
// the palette with the carried query IMMEDIATELY (the palette element renders
|
|
697
|
+
// unconditionally, so it doesn't need the setting to have landed). Awaiting
|
|
698
|
+
// the server write first read as a dead click on slow links.
|
|
699
|
+
this.LegacySearchOpen = false;
|
|
700
|
+
this.cdr.detectChanges();
|
|
701
|
+
this.OpenOmnibar(query?.trim() ?? '');
|
|
702
|
+
void UserInfoEngine.Instance.SetSetting(OMNIBAR_USER_SETTING_KEY, 'true').then((saved) => {
|
|
703
|
+
if (!saved) {
|
|
704
|
+
LogError('Omnibar promo opt-in failed to persist — palette will open for this session only');
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
/** Promo dismissed: persist server-side so it never shows again, on any device. */
|
|
709
|
+
OnOmnibarPromoDismissed() {
|
|
710
|
+
UserInfoEngine.Instance.SetSettingDebounced(OMNIBAR_PROMO_DISMISSED_KEY, 'true');
|
|
711
|
+
}
|
|
712
|
+
/** Palette footer gear → My Profile (where the Command Palette section lives). */
|
|
713
|
+
OnPaletteSettingsRequested() {
|
|
714
|
+
this.profileDialogService.open(this.viewContainerRef, {
|
|
715
|
+
avatarUrl: this.userImageURL || null,
|
|
716
|
+
avatarIconClass: this.userIconClass || null
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
omnibarPalette;
|
|
720
|
+
/** Legacy inline search composite (omnibar-off desktop). Structural typing keeps
|
|
721
|
+
the shell decoupled from the ng-search component class. */
|
|
722
|
+
shellSearchComposite;
|
|
723
|
+
/** Header affordance click → open the palette. */
|
|
724
|
+
OpenOmnibar(initialQuery = '') {
|
|
725
|
+
this.omnibarPalette?.Open(initialQuery);
|
|
550
726
|
}
|
|
551
727
|
// Tab container reference for thumbnail capture
|
|
552
728
|
tabContainerRef;
|
|
@@ -1562,7 +1738,12 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
1562
1738
|
case 'records':
|
|
1563
1739
|
// /app/:appName/record/:entityName/:recordId
|
|
1564
1740
|
if (entityName && recordId) {
|
|
1565
|
-
|
|
1741
|
+
// recordId is a CompositeKey URL segment ("ID|<value>") — the '|' MUST be encoded.
|
|
1742
|
+
// Angular's UrlSerializer percent-encodes '|' to %7C in router.url, so if we embed it raw
|
|
1743
|
+
// here, `syncUrlWithWorkspace`'s `currentUrl !== newUrl` check is permanently true and can
|
|
1744
|
+
// drive a re-navigation loop (with onSameUrlNavigation:'reload'). The read side already
|
|
1745
|
+
// decodeURIComponent()s this segment, so encoding here keeps both sides consistent.
|
|
1746
|
+
return appendQP(`/app/${encodeURIComponent(appPath)}/record/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`);
|
|
1566
1747
|
}
|
|
1567
1748
|
break;
|
|
1568
1749
|
case 'user views':
|
|
@@ -1634,7 +1815,9 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
1634
1815
|
switch (resourceType) {
|
|
1635
1816
|
case 'records':
|
|
1636
1817
|
if (entityName && recordId) {
|
|
1637
|
-
|
|
1818
|
+
// Encode the CompositeKey segment ('|' → %7C) to match Angular's serialized router.url and
|
|
1819
|
+
// the decodeURIComponent() on the read side — see the app-scoped 'records' case above.
|
|
1820
|
+
return appendQP(`/resource/record/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`);
|
|
1638
1821
|
}
|
|
1639
1822
|
break;
|
|
1640
1823
|
case 'user views':
|
|
@@ -2561,19 +2744,27 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
2561
2744
|
* Cmd+/ (Mac) or Ctrl+/ (Windows) opens the command palette
|
|
2562
2745
|
*/
|
|
2563
2746
|
handleGlobalKeyboardShortcuts(event) {
|
|
2564
|
-
// Skip if user is typing in an input/textarea
|
|
2747
|
+
// Skip if user is typing in an input/textarea — EXCEPT when the omnibar is on:
|
|
2748
|
+
// a modal palette is summonable from anywhere (incl. the chat composer), like
|
|
2749
|
+
// Slack/Linear. The legacy path keeps the guard (its binding steals focus).
|
|
2565
2750
|
const target = event.target;
|
|
2566
|
-
|
|
2751
|
+
const inEditable = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
|
|
2752
|
+
if (inEditable && !this.UseOmnibar) {
|
|
2567
2753
|
return;
|
|
2568
2754
|
}
|
|
2569
2755
|
// Platform detection
|
|
2570
2756
|
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
|
2571
2757
|
const isCtrlOrCmd = isMac ? event.metaKey : event.ctrlKey;
|
|
2572
|
-
// Cmd+/ or Ctrl+/ opens
|
|
2758
|
+
// Cmd+/ or Ctrl+/ opens the palette (omnibar '/' mode when enabled, legacy otherwise)
|
|
2573
2759
|
if (isCtrlOrCmd && event.key === '/') {
|
|
2574
2760
|
event.preventDefault();
|
|
2575
2761
|
event.stopPropagation();
|
|
2576
|
-
this.
|
|
2762
|
+
if (this.UseOmnibar) {
|
|
2763
|
+
this.OpenOmnibar('/');
|
|
2764
|
+
}
|
|
2765
|
+
else {
|
|
2766
|
+
this.commandPaletteService.Open();
|
|
2767
|
+
}
|
|
2577
2768
|
}
|
|
2578
2769
|
}
|
|
2579
2770
|
/**
|
|
@@ -2679,6 +2870,10 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
2679
2870
|
* Toggle search popup visibility
|
|
2680
2871
|
*/
|
|
2681
2872
|
toggleSearch() {
|
|
2873
|
+
if (this.UseOmnibar) {
|
|
2874
|
+
this.OpenOmnibar();
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2682
2877
|
this.isSearchOpen = !this.isSearchOpen;
|
|
2683
2878
|
// Focus on search input when opened
|
|
2684
2879
|
if (this.isSearchOpen) {
|
|
@@ -2729,17 +2924,41 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
2729
2924
|
// UNIVERSAL SEARCH EVENT HANDLERS
|
|
2730
2925
|
// ========================================
|
|
2731
2926
|
OnGlobalKeydown(event) {
|
|
2927
|
+
// Ctrl/Cmd+K summons search. Omnibar: the modal palette opens from anywhere,
|
|
2928
|
+
// even while typing (explicit chord, Slack/Linear semantics). Legacy: the
|
|
2929
|
+
// chord FOCUSES the inline header composite on desktop (results attach
|
|
2930
|
+
// beneath it), so keep the don't-steal-focus-mid-typing guard; on mobile
|
|
2931
|
+
// (no composite rendered) it opens the Spotlight overlay instead.
|
|
2732
2932
|
const target = event.target;
|
|
2733
|
-
|
|
2933
|
+
const inEditable = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
|
|
2934
|
+
if (inEditable && !this.UseOmnibar) {
|
|
2734
2935
|
return;
|
|
2936
|
+
}
|
|
2735
2937
|
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
|
2736
2938
|
const isCtrlOrCmd = isMac ? event.metaKey : event.ctrlKey;
|
|
2737
2939
|
if (isCtrlOrCmd && event.key === 'k') {
|
|
2738
2940
|
event.preventDefault();
|
|
2739
2941
|
event.stopPropagation();
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2942
|
+
this.OnHeaderSearchClick();
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
/** Header search affordance / Ctrl+K: route to whichever search surface applies.
|
|
2946
|
+
The mobile check matters: below the breakpoint the composite is CSS-hidden
|
|
2947
|
+
(.desktop-only) but its ViewChild still exists — focusing an invisible input
|
|
2948
|
+
would silently eat the interaction. */
|
|
2949
|
+
OnHeaderSearchClick() {
|
|
2950
|
+
const isMobile = window.matchMedia('(max-width: 768px)').matches;
|
|
2951
|
+
if (this.UseOmnibar) {
|
|
2952
|
+
this.OpenOmnibar();
|
|
2953
|
+
}
|
|
2954
|
+
else if (!isMobile && this.shellSearchComposite?.Focus) {
|
|
2955
|
+
// Omnibar-off desktop: the inline composite is on screen — focus it and
|
|
2956
|
+
// let its attached suggest dropdown do the work.
|
|
2957
|
+
this.shellSearchComposite.Focus();
|
|
2958
|
+
}
|
|
2959
|
+
else {
|
|
2960
|
+
// Omnibar-off mobile: no visible inline composite — open the Spotlight overlay.
|
|
2961
|
+
this.LegacySearchOpen = true;
|
|
2743
2962
|
}
|
|
2744
2963
|
}
|
|
2745
2964
|
OnSearchResultSelected(result) {
|
|
@@ -2755,6 +2974,19 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
2755
2974
|
const pkey = new CompositeKey([{ FieldName: 'ID', Value: result.RecordID }]);
|
|
2756
2975
|
this.navigationService.OpenEntityRecord(result.EntityName, pkey);
|
|
2757
2976
|
}
|
|
2977
|
+
/** Legacy search overlay selection → same navigation path as the old composite. */
|
|
2978
|
+
OnOverlayResultSelected(event) {
|
|
2979
|
+
this.LegacySearchOpen = false;
|
|
2980
|
+
this.OnSearchResultSelected(event.Result);
|
|
2981
|
+
}
|
|
2982
|
+
/** Legacy search overlay "See all results" → the full Search Results workspace
|
|
2983
|
+
(same destination as the omnibar's see-all row). */
|
|
2984
|
+
OnOverlaySeeAll(query) {
|
|
2985
|
+
this.LegacySearchOpen = false;
|
|
2986
|
+
this.navigationService.OpenSearch(query);
|
|
2987
|
+
}
|
|
2988
|
+
/** Inline composite submit (Enter) → full Search Results workspace, carrying the
|
|
2989
|
+
composite's relevance/scope selections. */
|
|
2758
2990
|
OnSearchSubmitted(query) {
|
|
2759
2991
|
if (query && query.trim().length >= 2) {
|
|
2760
2992
|
const minRelevance = this.shellSearchComposite?.MinRelevancePercent;
|
|
@@ -2767,6 +2999,7 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
2767
2999
|
this.navigationService.OpenSearch(query, Object.keys(opts).length > 0 ? opts : undefined);
|
|
2768
3000
|
}
|
|
2769
3001
|
}
|
|
3002
|
+
/** Inline composite's suggest-dropdown "See all N results" footer. */
|
|
2770
3003
|
OnSeeAllSearch(query) {
|
|
2771
3004
|
this.OnSearchSubmitted(query);
|
|
2772
3005
|
}
|
|
@@ -3106,138 +3339,138 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
3106
3339
|
}
|
|
3107
3340
|
static ɵfac = function ShellComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShellComponent)(i0.ɵɵdirectiveInject(i1.ApplicationManager), i0.ɵɵdirectiveInject(i1.WorkspaceStateManager), i0.ɵɵdirectiveInject(i1.GoldenLayoutManager), i0.ɵɵdirectiveInject(i1.TabService), i0.ɵɵdirectiveInject(i2.NavigationService), i0.ɵɵdirectiveInject(i3.ActivatedRoute), i0.ɵɵdirectiveInject(i3.Router), i0.ɵɵdirectiveInject(i4.MJAuthBase), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i5.UserAvatarService), i0.ɵɵdirectiveInject(i6.UserSharingCenterDialogService), i0.ɵɵdirectiveInject(i7.AboutDialogService), i0.ɵɵdirectiveInject(i8.ProfileDialogService), i0.ɵɵdirectiveInject(i0.ViewContainerRef), i0.ɵɵdirectiveInject(i2.TitleService), i0.ɵɵdirectiveInject(i2.DeveloperModeService), i0.ɵɵdirectiveInject(i9.StartupValidationService), i0.ɵɵdirectiveInject(i10.CommandPaletteService), i0.ɵɵdirectiveInject(i2.ThemeService), i0.ɵɵdirectiveInject(i2.HomeAppPinService), i0.ɵɵdirectiveInject(i11.FileOpenService), i0.ɵɵdirectiveInject(i12.FeedbackDialogService), i0.ɵɵdirectiveInject(i12.FeedbackService), i0.ɵɵdirectiveInject(i2.ActivityService)); };
|
|
3108
3341
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ShellComponent, selectors: [["mj-shell"]], viewQuery: function ShellComponent_Query(rf, ctx) { if (rf & 1) {
|
|
3109
|
-
i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(TabContainerComponent, 5)(
|
|
3342
|
+
i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(_c2, 5)(TabContainerComponent, 5)(_c3, 5);
|
|
3110
3343
|
} if (rf & 2) {
|
|
3111
3344
|
let _t;
|
|
3112
3345
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchInput = _t.first);
|
|
3346
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.omnibarPalette = _t.first);
|
|
3113
3347
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.shellSearchComposite = _t.first);
|
|
3114
3348
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.tabContainerRef = _t.first);
|
|
3115
3349
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.appAccessDialog = _t.first);
|
|
3116
3350
|
} }, hostBindings: function ShellComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
3117
3351
|
i0.ɵɵlistener("keydown", function ShellComponent_keydown_HostBindingHandler($event) { return ctx.OnGlobalKeydown($event); }, i0.ɵɵresolveDocument)("click", function ShellComponent_click_HostBindingHandler() { return ctx.onDocumentClickCloseActivity(); }, i0.ɵɵresolveDocument);
|
|
3118
|
-
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls:
|
|
3352
|
+
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 50, vars: 28, consts: [["searchInput", ""], ["appAccessDialog", ""], ["omnibarPalette", ""], ["shellSearchComposite", ""], [1, "shell-container"], [1, "shell-header"], ["title", "MemberJunction", 1, "mj-logo"], ["title", "Menu", 1, "hamburger-btn", 3, "click"], [1, "fa-solid", "fa-bars"], [1, "nav-bar-apps", "left-of-switcher"], [3, "activeApp", "isViewingSystemTab", "loadingAppId"], [1, "desktop-nav", 3, "app"], [1, "spacer"], [1, "header-actions"], [1, "activity-wrap"], ["title", "Notifications", 1, "icon-btn", "desktop-only", "notification-btn"], [1, "nav-bar-apps", "left-of-user-menu"], [1, "user-menu"], [1, "avatar-btn", 3, "click"], ["alt", "User avatar", 1, "avatar-img", 3, "src"], [1, "icon-fallback"], [1, "user-context-menu", 3, "menu-fade", "menu-slide"], [1, "search-popup-overlay"], [1, "search-popup"], [1, "search-popup-content", 3, "click"], ["TextField", "Name", "ValueField", "ID", 1, "search-entity-dropdown", 3, "ngModelChange", "Data", "ngModel"], ["type", "text", "placeholder", "Search...", 1, "mj-input", "search-input", 3, "keydown.enter"], ["title", "Search", 1, "search-submit-btn", 3, "click"], [1, "fa-solid", "fa-search"], [1, "mobile-nav-overlay"], [1, "mobile-nav-drawer"], [1, "mobile-nav-header"], [1, "close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "mobile-nav-content"], [1, "mobile-nav-footer"], ["title", "Search", 1, "mobile-nav-action", 3, "click"], ["title", "Notifications", 1, "mobile-nav-action"], [3, "firstResourceLoadComplete", "layoutInitError"], [1, "shell-loading"], [3, "result"], [3, "AppSelected"], [3, "SettingsRequested"], ["Placeholder", "Search everything...", 3, "IsOpen", "EnableGlobalShortcut", "ShowPromo", "PromoText"], [1, "pin-progress-backdrop"], [1, "nav-bar-app-btn", 3, "active", "title", "--app-color"], [1, "nav-bar-app-btn", 3, "click", "dblclick", "title"], [3, "appSelected", "activeApp", "isViewingSystemTab", "loadingAppId"], [1, "desktop-nav", 3, "navItemClick", "navItemDismiss", "app"], ["title", "Search everything", 1, "search-btn"], ["title", "Search everything", 1, "search-btn", 3, "click"], [1, "fa-solid", "fa-magnifying-glass"], [1, "search-btn-text", "desktop-only"], ["aria-hidden", "true", 1, "search-btn-kbd", "desktop-only"], [1, "shell-search-bar", "desktop-only"], ["Placeholder", "Search everything...", 3, "ResultSelected", "SearchSubmitted", "SeeAllRequested", "RecentRecordSelected", "PromoAccepted", "PromoDismissed", "ShowShortcutHint", "EnablePreview", "EnableRecent", "MaxPreviewResults", "ShowPromo", "PromoText"], ["title", "Search everything", 1, "search-btn", "search-btn-mobile", 3, "click"], ["title", "Activity", 1, "icon-btn", "desktop-only", "activity-btn", 3, "click"], [1, "fa-solid", "fa-wave-square"], [1, "activity-badge"], [1, "activity-drawer"], [1, "activity-drawer", 3, "click"], [1, "activity-drawer-head"], ["title", "Clear finished", 1, "activity-clear", 3, "click"], [1, "fa-solid", "fa-broom"], [1, "activity-list"], [1, "activity-row", 3, "is-error"], [1, "activity-row"], [1, "activity-row-icon"], [1, "activity-row-body"], [1, "activity-row-label"], [1, "activity-row-detail"], [1, "activity-bar"], [1, "activity-bar-fill"], ["title", "Notifications", 1, "icon-btn", "desktop-only", "notification-btn", 3, "click"], [1, "fa-solid", "fa-bell"], [1, "notification-badge"], [1, "user-context-menu"], [1, "user-menu-header"], [1, "user-info"], [1, "user-name"], [1, "user-email"], [1, "user-subtitle"], [1, "user-menu-divider"], [1, "user-menu-item", "theme-toggle-item", 3, "title"], [1, "user-menu-item", 3, "disabled", "danger", "color", "title"], [1, "user-menu-item", "theme-toggle-item", 3, "click", "title"], [1, "menu-label"], [1, "theme-toggle-track"], [1, "theme-toggle-thumb"], [1, "theme-toggle-icon"], [1, "user-menu-item", 3, "click", "title"], [1, "menu-shortcut"], [1, "search-popup-overlay", 3, "click"], [1, "mobile-nav-overlay", 3, "click"], [1, "mobile-nav-section-title"], [3, "navItemClick", "navItemDismiss", "app"], ["title", "Notifications", 1, "mobile-nav-action", 3, "click"], [1, "notification-badge-mobile"], ["size", "large", 3, "text", "textColor", "logoColor", "logoGradient", "animation"], [1, "loading-reset-panel"], [1, "loading-version"], [1, "loading-reset-message"], [1, "fa-regular", "fa-clock"], [1, "loading-reset-hint"], [1, "loading-reset-btn", 3, "click"], [1, "fa-solid", "fa-arrows-rotate"], ["Placeholder", "Search everything...", 3, "IsOpenChange", "ResultSelected", "SeeAllRequested", "PromoAccepted", "PromoDismissed", "IsOpen", "EnableGlobalShortcut", "ShowPromo", "PromoText"], [1, "pin-progress-modal"], ["size", "small", 3, "showText"], [1, "pin-progress-text"]], template: function ShellComponent_Template(rf, ctx) { if (rf & 1) {
|
|
3119
3353
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
3120
|
-
i0.ɵɵelementStart(0, "div",
|
|
3121
|
-
i0.ɵɵelement(2, "div",
|
|
3122
|
-
i0.ɵɵelementStart(3, "button",
|
|
3354
|
+
i0.ɵɵelementStart(0, "div", 4)(1, "header", 5);
|
|
3355
|
+
i0.ɵɵelement(2, "div", 6);
|
|
3356
|
+
i0.ɵɵelementStart(3, "button", 7);
|
|
3123
3357
|
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleMobileNav()); });
|
|
3124
|
-
i0.ɵɵelement(4, "i",
|
|
3358
|
+
i0.ɵɵelement(4, "i", 8);
|
|
3125
3359
|
i0.ɵɵelementEnd();
|
|
3126
|
-
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_5_Template, 3, 0, "div",
|
|
3127
|
-
i0.ɵɵconditionalCreate(6, ShellComponent_Conditional_6_Template, 1, 3, "mj-app-switcher",
|
|
3128
|
-
i0.ɵɵconditionalCreate(7, ShellComponent_Conditional_7_Template, 1, 1, "mj-app-nav",
|
|
3129
|
-
i0.ɵɵ
|
|
3130
|
-
i0.ɵɵ
|
|
3131
|
-
i0.ɵɵ
|
|
3360
|
+
i0.ɵɵconditionalCreate(5, ShellComponent_Conditional_5_Template, 3, 0, "div", 9);
|
|
3361
|
+
i0.ɵɵconditionalCreate(6, ShellComponent_Conditional_6_Template, 1, 3, "mj-app-switcher", 10);
|
|
3362
|
+
i0.ɵɵconditionalCreate(7, ShellComponent_Conditional_7_Template, 1, 1, "mj-app-nav", 11);
|
|
3363
|
+
i0.ɵɵelement(8, "div", 12);
|
|
3364
|
+
i0.ɵɵelementStart(9, "div", 13);
|
|
3365
|
+
i0.ɵɵconditionalCreate(10, ShellComponent_Conditional_10_Template, 2, 1);
|
|
3132
3366
|
i0.ɵɵconditionalCreate(11, ShellComponent_Conditional_11_Template, 5, 4, "div", 14);
|
|
3133
|
-
i0.ɵɵ
|
|
3134
|
-
i0.ɵɵ
|
|
3135
|
-
i0.ɵɵ
|
|
3136
|
-
i0.ɵɵ
|
|
3137
|
-
i0.ɵɵ
|
|
3138
|
-
i0.ɵɵconditionalCreate(15, ShellComponent_Conditional_15_Template, 3, 0, "div", 18);
|
|
3139
|
-
i0.ɵɵelementStart(16, "div", 19)(17, "button", 20);
|
|
3140
|
-
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_17_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleUserMenu($event)); });
|
|
3141
|
-
i0.ɵɵconditionalCreate(18, ShellComponent_Conditional_18_Template, 1, 1, "img", 21)(19, ShellComponent_Conditional_19_Template, 2, 2, "div", 22);
|
|
3367
|
+
i0.ɵɵconditionalCreate(12, ShellComponent_Conditional_12_Template, 3, 1, "button", 15);
|
|
3368
|
+
i0.ɵɵconditionalCreate(13, ShellComponent_Conditional_13_Template, 3, 0, "div", 16);
|
|
3369
|
+
i0.ɵɵelementStart(14, "div", 17)(15, "button", 18);
|
|
3370
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_15_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.toggleUserMenu($event)); });
|
|
3371
|
+
i0.ɵɵconditionalCreate(16, ShellComponent_Conditional_16_Template, 1, 1, "img", 19)(17, ShellComponent_Conditional_17_Template, 2, 2, "div", 20);
|
|
3142
3372
|
i0.ɵɵelementEnd();
|
|
3143
|
-
i0.ɵɵconditionalCreate(
|
|
3373
|
+
i0.ɵɵconditionalCreate(18, ShellComponent_Conditional_18_Template, 4, 5, "div", 21);
|
|
3144
3374
|
i0.ɵɵelementEnd()()();
|
|
3145
|
-
i0.ɵɵconditionalCreate(
|
|
3146
|
-
i0.ɵɵelementStart(
|
|
3147
|
-
i0.ɵɵlistener("click", function
|
|
3148
|
-
i0.ɵɵelementStart(
|
|
3149
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
3375
|
+
i0.ɵɵconditionalCreate(19, ShellComponent_Conditional_19_Template, 1, 0, "div", 22);
|
|
3376
|
+
i0.ɵɵelementStart(20, "div", 23)(21, "div", 24);
|
|
3377
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_div_click_21_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
3378
|
+
i0.ɵɵelementStart(22, "mj-dropdown", 25);
|
|
3379
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ShellComponent_Template_mj_dropdown_ngModelChange_22_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.selectedEntity, $event) || (ctx.selectedEntity = $event); return i0.ɵɵresetView($event); });
|
|
3150
3380
|
i0.ɵɵelementEnd();
|
|
3151
|
-
i0.ɵɵelementStart(
|
|
3152
|
-
i0.ɵɵlistener("keydown.enter", function
|
|
3381
|
+
i0.ɵɵelementStart(23, "input", 26, 0);
|
|
3382
|
+
i0.ɵɵlistener("keydown.enter", function ShellComponent_Template_input_keydown_enter_23_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
|
|
3153
3383
|
i0.ɵɵelementEnd();
|
|
3154
|
-
i0.ɵɵelementStart(
|
|
3155
|
-
i0.ɵɵlistener("click", function
|
|
3156
|
-
i0.ɵɵelement(
|
|
3384
|
+
i0.ɵɵelementStart(25, "button", 27);
|
|
3385
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_25_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearch($event)); });
|
|
3386
|
+
i0.ɵɵelement(26, "i", 28);
|
|
3157
3387
|
i0.ɵɵelementEnd()()();
|
|
3158
|
-
i0.ɵɵconditionalCreate(
|
|
3159
|
-
i0.ɵɵelementStart(
|
|
3160
|
-
i0.ɵɵtext(
|
|
3388
|
+
i0.ɵɵconditionalCreate(27, ShellComponent_Conditional_27_Template, 1, 0, "div", 29);
|
|
3389
|
+
i0.ɵɵelementStart(28, "div", 30)(29, "div", 31)(30, "span");
|
|
3390
|
+
i0.ɵɵtext(31, "Navigation");
|
|
3161
3391
|
i0.ɵɵelementEnd();
|
|
3162
|
-
i0.ɵɵelementStart(
|
|
3163
|
-
i0.ɵɵlistener("click", function
|
|
3164
|
-
i0.ɵɵelement(
|
|
3392
|
+
i0.ɵɵelementStart(32, "button", 32);
|
|
3393
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.closeMobileNav()); });
|
|
3394
|
+
i0.ɵɵelement(33, "i", 33);
|
|
3165
3395
|
i0.ɵɵelementEnd()();
|
|
3166
|
-
i0.ɵɵconditionalCreate(
|
|
3167
|
-
i0.ɵɵelementStart(
|
|
3168
|
-
i0.ɵɵlistener("click", function
|
|
3169
|
-
i0.ɵɵelement(
|
|
3170
|
-
i0.ɵɵelementStart(
|
|
3171
|
-
i0.ɵɵtext(
|
|
3396
|
+
i0.ɵɵconditionalCreate(34, ShellComponent_Conditional_34_Template, 4, 2, "div", 34);
|
|
3397
|
+
i0.ɵɵelementStart(35, "div", 35)(36, "button", 36);
|
|
3398
|
+
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_36_listener() { i0.ɵɵrestoreView(_r1); ctx.toggleSearch(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
|
|
3399
|
+
i0.ɵɵelement(37, "i", 28);
|
|
3400
|
+
i0.ɵɵelementStart(38, "span");
|
|
3401
|
+
i0.ɵɵtext(39, "Search");
|
|
3172
3402
|
i0.ɵɵelementEnd()();
|
|
3173
|
-
i0.ɵɵ
|
|
3174
|
-
i0.ɵɵlistener("click", function ShellComponent_Template_button_click_42_listener() { i0.ɵɵrestoreView(_r1); ctx.showNotifications(); return i0.ɵɵresetView(ctx.closeMobileNav()); });
|
|
3175
|
-
i0.ɵɵelement(43, "i", 16);
|
|
3176
|
-
i0.ɵɵelementStart(44, "span");
|
|
3177
|
-
i0.ɵɵtext(45, "Notifications");
|
|
3178
|
-
i0.ɵɵelementEnd();
|
|
3179
|
-
i0.ɵɵconditionalCreate(46, ShellComponent_Conditional_46_Template, 2, 1, "span", 40);
|
|
3180
|
-
i0.ɵɵelementEnd()()();
|
|
3181
|
-
i0.ɵɵelementStart(47, "mj-tab-container", 41);
|
|
3182
|
-
i0.ɵɵlistener("firstResourceLoadComplete", function ShellComponent_Template_mj_tab_container_firstResourceLoadComplete_47_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onFirstResourceLoadComplete()); })("layoutInitError", function ShellComponent_Template_mj_tab_container_layoutInitError_47_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleLayoutError()); });
|
|
3403
|
+
i0.ɵɵconditionalCreate(40, ShellComponent_Conditional_40_Template, 5, 1, "button", 37);
|
|
3183
3404
|
i0.ɵɵelementEnd()();
|
|
3184
|
-
i0.ɵɵ
|
|
3185
|
-
i0.ɵɵ
|
|
3186
|
-
i0.ɵɵ
|
|
3405
|
+
i0.ɵɵelementStart(41, "mj-tab-container", 38);
|
|
3406
|
+
i0.ɵɵlistener("firstResourceLoadComplete", function ShellComponent_Template_mj_tab_container_firstResourceLoadComplete_41_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onFirstResourceLoadComplete()); })("layoutInitError", function ShellComponent_Template_mj_tab_container_layoutInitError_41_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleLayoutError()); });
|
|
3407
|
+
i0.ɵɵelementEnd()();
|
|
3408
|
+
i0.ɵɵconditionalCreate(42, ShellComponent_Conditional_42_Template, 4, 6, "div", 39);
|
|
3409
|
+
i0.ɵɵelementStart(43, "mj-app-access-dialog", 40, 1);
|
|
3410
|
+
i0.ɵɵlistener("result", function ShellComponent_Template_mj_app_access_dialog_result_43_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppAccessDialogResult($event)); });
|
|
3411
|
+
i0.ɵɵelementEnd();
|
|
3412
|
+
i0.ɵɵelementStart(45, "mj-command-palette", 41);
|
|
3413
|
+
i0.ɵɵlistener("AppSelected", function ShellComponent_Template_mj_command_palette_AppSelected_45_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAppSwitch($event)); });
|
|
3187
3414
|
i0.ɵɵelementEnd();
|
|
3188
|
-
i0.ɵɵelementStart(
|
|
3189
|
-
i0.ɵɵlistener("
|
|
3415
|
+
i0.ɵɵelementStart(46, "mj-omnibar-palette", 42, 2);
|
|
3416
|
+
i0.ɵɵlistener("SettingsRequested", function ShellComponent_Template_mj_omnibar_palette_SettingsRequested_46_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnPaletteSettingsRequested()); });
|
|
3190
3417
|
i0.ɵɵelementEnd();
|
|
3191
|
-
i0.ɵɵconditionalCreate(
|
|
3418
|
+
i0.ɵɵconditionalCreate(48, ShellComponent_Conditional_48_Template, 1, 4, "mj-search-overlay", 43);
|
|
3419
|
+
i0.ɵɵconditionalCreate(49, ShellComponent_Conditional_49_Template, 5, 2, "div", 44);
|
|
3192
3420
|
} if (rf & 2) {
|
|
3193
3421
|
i0.ɵɵclassProp("hidden", ctx.loading)("tabs-visible", ctx.tabBarVisible);
|
|
3194
3422
|
i0.ɵɵadvance(5);
|
|
3195
3423
|
i0.ɵɵconditional(ctx.leftOfSwitcherApps.length > 0 && !ctx.appSwitchingLocked ? 5 : -1);
|
|
3196
3424
|
i0.ɵɵadvance();
|
|
3197
|
-
i0.ɵɵconditional(!ctx.appSwitchingLocked ? 6 : -1);
|
|
3198
|
-
i0.ɵɵadvance();
|
|
3199
|
-
i0.ɵɵconditional(ctx.activeApp ? 7 : -1);
|
|
3425
|
+
i0.ɵɵconditional(!ctx.appSwitchingLocked && ctx.ShowAppSwitcher ? 6 : -1);
|
|
3200
3426
|
i0.ɵɵadvance();
|
|
3201
|
-
i0.ɵɵconditional(ctx.
|
|
3427
|
+
i0.ɵɵconditional(ctx.activeApp && ctx.ShowAppNav ? 7 : -1);
|
|
3202
3428
|
i0.ɵɵadvance(3);
|
|
3429
|
+
i0.ɵɵconditional(ctx.ShowSearchBar ? 10 : -1);
|
|
3430
|
+
i0.ɵɵadvance();
|
|
3203
3431
|
i0.ɵɵconditional(ctx.activityItems.length > 0 ? 11 : -1);
|
|
3204
|
-
i0.ɵɵadvance(3);
|
|
3205
|
-
i0.ɵɵconditional(ctx.unreadNotificationCount > 0 ? 14 : -1);
|
|
3206
3432
|
i0.ɵɵadvance();
|
|
3207
|
-
i0.ɵɵconditional(ctx.
|
|
3433
|
+
i0.ɵɵconditional(ctx.ShowNotifications ? 12 : -1);
|
|
3434
|
+
i0.ɵɵadvance();
|
|
3435
|
+
i0.ɵɵconditional(ctx.leftOfUserMenuApps.length > 0 ? 13 : -1);
|
|
3208
3436
|
i0.ɵɵadvance(3);
|
|
3209
|
-
i0.ɵɵconditional(ctx.userImageURL ?
|
|
3437
|
+
i0.ɵɵconditional(ctx.userImageURL ? 16 : 17);
|
|
3210
3438
|
i0.ɵɵadvance(2);
|
|
3211
|
-
i0.ɵɵconditional(ctx.userMenuVisible ?
|
|
3439
|
+
i0.ɵɵconditional(ctx.userMenuVisible ? 18 : -1);
|
|
3212
3440
|
i0.ɵɵadvance();
|
|
3213
|
-
i0.ɵɵconditional(ctx.isSearchOpen ?
|
|
3441
|
+
i0.ɵɵconditional(ctx.isSearchOpen ? 19 : -1);
|
|
3214
3442
|
i0.ɵɵadvance();
|
|
3215
3443
|
i0.ɵɵclassProp("open", ctx.isSearchOpen);
|
|
3216
3444
|
i0.ɵɵadvance(2);
|
|
3217
3445
|
i0.ɵɵproperty("Data", ctx.searchableEntities);
|
|
3218
3446
|
i0.ɵɵtwoWayProperty("ngModel", ctx.selectedEntity);
|
|
3219
3447
|
i0.ɵɵadvance(5);
|
|
3220
|
-
i0.ɵɵconditional(ctx.mobileNavOpen ?
|
|
3448
|
+
i0.ɵɵconditional(ctx.mobileNavOpen ? 27 : -1);
|
|
3221
3449
|
i0.ɵɵadvance();
|
|
3222
3450
|
i0.ɵɵclassProp("open", ctx.mobileNavOpen);
|
|
3223
3451
|
i0.ɵɵadvance(6);
|
|
3224
|
-
i0.ɵɵconditional(ctx.activeApp ?
|
|
3225
|
-
i0.ɵɵadvance(
|
|
3226
|
-
i0.ɵɵconditional(ctx.
|
|
3452
|
+
i0.ɵɵconditional(ctx.activeApp && ctx.ShowAppNav ? 34 : -1);
|
|
3453
|
+
i0.ɵɵadvance(6);
|
|
3454
|
+
i0.ɵɵconditional(ctx.ShowNotifications ? 40 : -1);
|
|
3227
3455
|
i0.ɵɵadvance();
|
|
3228
3456
|
i0.ɵɵclassProp("hide-tab-bar", !ctx.tabBarVisible);
|
|
3229
3457
|
i0.ɵɵadvance();
|
|
3230
|
-
i0.ɵɵconditional(ctx.loading ?
|
|
3231
|
-
i0.ɵɵadvance(
|
|
3232
|
-
i0.ɵɵconditional(ctx.
|
|
3233
|
-
} }, dependencies: [i13.NgControlStatus, i13.NgModel, i14.MJDropdownComponent, i15.LoadingComponent, i16.SearchCompositeComponent, i17.AppSwitcherComponent, i18.AppNavComponent, i19.TabContainerComponent, i20.AppAccessDialogComponent, i21.CommandPaletteComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n.mj-logo[_ngcontent-%COMP%] {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: relative;\n}\n\n\n\n\n.shell-container.hidden[_ngcontent-%COMP%] {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_header {\n display: none;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%]:not(.hide-tab-bar) .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_content {\n height: 100% !important;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%] .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header[_ngcontent-%COMP%] {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n \n\n\n position: relative;\n z-index: 500;\n}\n\n\n\n.nav-bar-apps[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher[_ngcontent-%COMP%] {\n \n\n \n\n}\n\n.nav-bar-apps.left-of-user-menu[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.15s ease;\n margin-top: 2px; \n\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n.spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.notification-btn[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.notification-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .icon-fallback[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .avatar-img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .avatar-img[_ngcontent-%COMP%] {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n\n\n.user-menu-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.user-context-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n.user-menu-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n\n\n.theme-toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.theme-toggle-track[_ngcontent-%COMP%] {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-thumb[_ngcontent-%COMP%] {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n\n\n.user-menu-item[_ngcontent-%COMP%] .menu-shortcut[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n\n\n.user-context-menu.menu-fade[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuSlideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n z-index: 99999;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n.loading-version[_ngcontent-%COMP%] {\n margin-top: var(--mj-space-8, 24px);\n font-size: 11px;\n color: var(--mj-text-muted);\n letter-spacing: 0.4px;\n opacity: 0.6;\n user-select: none;\n}\n\n\n\n.loading-reset-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: _ngcontent-%COMP%_resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes _ngcontent-%COMP%_resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.hamburger-btn[_ngcontent-%COMP%] {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n\n\n.mobile-nav-drawer[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.mobile-nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title[_ngcontent-%COMP%] {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n\n\n@media (max-width: 768px) {\n .hamburger-btn[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .desktop-nav[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n }\n\n .mobile-nav-drawer[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .shell-header[_ngcontent-%COMP%] {\n padding: 0 12px;\n gap: 8px;\n }\n\n \n\n\n\n .header-actions[_ngcontent-%COMP%] {\n flex-direction: row;\n flex-wrap: nowrap;\n }\n .header-actions[_ngcontent-%COMP%] .user-menu[_ngcontent-%COMP%], \n .header-actions[_ngcontent-%COMP%] .nav-bar-apps[_ngcontent-%COMP%] {\n flex-shrink: 0;\n }\n}\n\n\n\n .settings-fullscreen-window {\n \n\n box-shadow: none !important;\n border: none !important;\n}\n\n .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"], \n .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"], \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n\n\n\n\n.shell-search-bar[_ngcontent-%COMP%] {\n flex: 0 1 420px;\n min-width: 200px;\n max-width: 520px;\n margin: 0 12px;\n position: relative;\n z-index: 99999;\n}\n@media (max-width: 768px) {\n .shell-search-bar[_ngcontent-%COMP%] { display: none; }\n}\n\n\n\n\n\n\n.search-popup-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: _ngcontent-%COMP%_fadeIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup[_ngcontent-%COMP%] {\n position: absolute;\n top: 60px; \n\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.notification-badge-mobile[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n\n\n@media (max-width: 768px) {\n .search-popup[_ngcontent-%COMP%] {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.pin-progress-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: _ngcontent-%COMP%_pinBackdropIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: _ngcontent-%COMP%_pinModalIn 0.25s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n\n\n\n.activity-wrap[_ngcontent-%COMP%] { position: relative; display: inline-flex; }\n.activity-btn[_ngcontent-%COMP%] { position: relative; }\n.activity-btn[_ngcontent-%COMP%] .activity-pulse[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n.activity-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 700;\n line-height: 16px;\n text-align: center;\n}\n.activity-drawer[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 320px;\n max-height: 420px;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 8px 28px color-mix(in srgb, var(--mj-text-primary) 18%, transparent);\n z-index: 1000;\n overflow: hidden;\n}\n.activity-drawer-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-weight: 700;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n.activity-clear[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 0.8rem;\n padding: 4px 6px;\n border-radius: 6px;\n}\n.activity-clear[_ngcontent-%COMP%]:hover { color: var(--mj-text-primary); background: var(--mj-bg-surface-hover); }\n.activity-list[_ngcontent-%COMP%] { overflow-y: auto; padding: 6px; }\n.activity-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n padding: 9px 8px;\n border-radius: 8px;\n}\n.activity-row[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n.activity-row-icon[_ngcontent-%COMP%] { margin-top: 2px; color: var(--mj-brand-primary); font-size: 0.85rem; }\n.activity-row.is-error[_ngcontent-%COMP%] .activity-row-icon[_ngcontent-%COMP%] { color: var(--mj-status-error); }\n.activity-row-body[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n.activity-row-label[_ngcontent-%COMP%] { font-size: 0.82rem; font-weight: 600; color: var(--mj-text-primary); }\n.activity-row-detail[_ngcontent-%COMP%] { font-size: 0.72rem; color: var(--mj-text-muted); margin-top: 1px; }\n.activity-bar[_ngcontent-%COMP%] {\n margin-top: 6px;\n height: 4px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 2px;\n overflow: hidden;\n}\n.activity-bar-fill[_ngcontent-%COMP%] { height: 100%; background: var(--mj-brand-primary); transition: width 0.3s ease; }"] });
|
|
3458
|
+
i0.ɵɵconditional(ctx.loading ? 42 : -1);
|
|
3459
|
+
i0.ɵɵadvance(6);
|
|
3460
|
+
i0.ɵɵconditional(ctx.ShowSearchBar && !ctx.UseOmnibar ? 48 : -1);
|
|
3461
|
+
i0.ɵɵadvance();
|
|
3462
|
+
i0.ɵɵconditional(ctx.PinProgressVisible ? 49 : -1);
|
|
3463
|
+
} }, dependencies: [i13.NgControlStatus, i13.NgModel, i14.MJDropdownComponent, i15.LoadingComponent, i16.SearchOverlayComponent, i16.SearchCompositeComponent, i17.AppSwitcherComponent, i18.AppNavComponent, i19.TabContainerComponent, i20.AppAccessDialogComponent, i21.CommandPaletteComponent, i22.OmnibarPaletteComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n\n\n\n\n\n.mj-logo[_ngcontent-%COMP%] {\n width: var(--mj-logo-width, 32px);\n height: var(--mj-logo-height, 18px);\n background-image: var(--mj-logo-mark);\n background-color: var(--mj-logo-plate-bg, transparent);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n border-radius: var(--mj-radius-sm, 4px);\n flex-shrink: 0;\n}\n\n.shell-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: relative;\n}\n\n\n\n\n.shell-container.hidden[_ngcontent-%COMP%] {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_header {\n display: none;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%]:not(.hide-tab-bar) .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n\n\nmj-tab-container.hide-tab-bar[_ngcontent-%COMP%] .lm_content {\n height: 100% !important;\n}\n\n\n\nmj-tab-container[_ngcontent-%COMP%] .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header[_ngcontent-%COMP%] {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n \n\n\n position: relative;\n z-index: 500;\n}\n\n\n\n.nav-bar-apps[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher[_ngcontent-%COMP%] {\n \n\n \n\n}\n\n.nav-bar-apps.left-of-user-menu[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n transition: transform 0.15s ease;\n margin-top: 2px; \n\n}\n\n.nav-bar-app-btn[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n transform: scale(1.1);\n}\n\n.spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n\n\n\n.search-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 260px;\n height: 36px;\n padding: 0 var(--mj-space-2-5) 0 var(--mj-space-3-5);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n font-family: inherit;\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.search-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n}\n\n.search-btn[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n\n\n\n.search-btn-mobile[_ngcontent-%COMP%] {\n display: none;\n}\n\n\n\n\n.shell-search-bar[_ngcontent-%COMP%] {\n position: relative;\n width: 260px;\n z-index: 99999;\n}\n\n\n\n\n\n.shell-search-bar[_ngcontent-%COMP%] .suggest-dropdown {\n left: auto;\n right: 0;\n width: min(560px, calc(100vw - var(--mj-space-6)));\n}\n\n.search-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n flex-shrink: 0;\n}\n\n.search-btn[_ngcontent-%COMP%] .search-btn-text[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n text-align: left;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n\n\n.search-btn[_ngcontent-%COMP%] .search-btn-kbd[_ngcontent-%COMP%] {\n flex-shrink: 0;\n white-space: nowrap;\n font-family: inherit;\n font-size: 10.5px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-bottom-width: 2px;\n border-radius: 5px;\n padding: 1.5px var(--mj-space-1-5);\n}\n\n\n\n.notification-btn[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.notification-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover {\n transform: scale(1.05);\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .icon-fallback[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .icon-fallback[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%] .avatar-img[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu[_ngcontent-%COMP%] .avatar-btn[_ngcontent-%COMP%]:hover .avatar-img[_ngcontent-%COMP%] {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n\n\n.user-menu-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-name[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-email[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header[_ngcontent-%COMP%] .user-subtitle[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n\n\n.user-context-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n\n\n.user-menu-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled[_ngcontent-%COMP%]:hover {\n background: transparent;\n}\n\n\n\n.theme-toggle-item[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.theme-toggle-track[_ngcontent-%COMP%] {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-thumb[_ngcontent-%COMP%] {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark[_ngcontent-%COMP%] .theme-toggle-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse);\n}\n\n\n\n.user-menu-item[_ngcontent-%COMP%] .menu-shortcut[_ngcontent-%COMP%] {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n\n\n.user-context-menu.menu-fade[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_menuSlideIn 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n z-index: 99999;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n.loading-version[_ngcontent-%COMP%] {\n margin-top: var(--mj-space-8, 24px);\n font-size: 11px;\n color: var(--mj-text-muted);\n letter-spacing: 0.4px;\n opacity: 0.6;\n user-select: none;\n}\n\n\n\n.loading-reset-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: _ngcontent-%COMP%_resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint[_ngcontent-%COMP%] {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes _ngcontent-%COMP%_resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.hamburger-btn[_ngcontent-%COMP%] {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n\n\n.mobile-nav-overlay[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n\n\n.mobile-nav-drawer[_ngcontent-%COMP%] {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open[_ngcontent-%COMP%] {\n transform: translateX(0);\n}\n\n.mobile-nav-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title[_ngcontent-%COMP%] {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer[_ngcontent-%COMP%] {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n\n\n@media (max-width: 768px) {\n .hamburger-btn[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .desktop-nav[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .desktop-only[_ngcontent-%COMP%] {\n display: none !important;\n }\n\n .mobile-nav-overlay[_ngcontent-%COMP%] {\n display: block;\n }\n\n .mobile-nav-drawer[_ngcontent-%COMP%] {\n display: flex;\n }\n\n .shell-header[_ngcontent-%COMP%] {\n padding: 0 12px;\n gap: 8px;\n }\n\n \n\n\n\n .header-actions[_ngcontent-%COMP%] {\n flex-direction: row;\n flex-wrap: nowrap;\n }\n .header-actions[_ngcontent-%COMP%] .user-menu[_ngcontent-%COMP%], \n .header-actions[_ngcontent-%COMP%] .nav-bar-apps[_ngcontent-%COMP%], \n .header-actions[_ngcontent-%COMP%] .search-btn[_ngcontent-%COMP%] {\n flex-shrink: 0;\n }\n\n \n\n\n\n\n .search-btn[_ngcontent-%COMP%] {\n display: flex;\n width: 40px;\n height: 40px;\n padding: 0;\n justify-content: center;\n border: none;\n border-radius: 50%;\n background: none;\n }\n .search-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: var(--mj-text-lg);\n }\n .search-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n border: none;\n }\n}\n\n\n\n .settings-fullscreen-window {\n \n\n box-shadow: none !important;\n border: none !important;\n}\n\n .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n\n\n .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"], \n .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"], \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize, \n .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n\n\n\n\n\n\n\n\n\n\n.search-popup-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: _ngcontent-%COMP%_fadeIn 0.15s ease;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup[_ngcontent-%COMP%] {\n position: absolute;\n top: 60px; \n\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown[_ngcontent-%COMP%] {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input[_ngcontent-%COMP%]:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-brand-primary-hover);\n}\n\n\n\n.notification-badge-mobile[_ngcontent-%COMP%] {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n\n\n@media (max-width: 768px) {\n .search-popup[_ngcontent-%COMP%] {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .search-input[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n }\n}\n\n\n\n\n\n.pin-progress-backdrop[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: _ngcontent-%COMP%_pinBackdropIn 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: _ngcontent-%COMP%_pinModalIn 0.25s ease;\n}\n\n@keyframes _ngcontent-%COMP%_pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text[_ngcontent-%COMP%] {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n\n\n\n.activity-wrap[_ngcontent-%COMP%] { position: relative; display: inline-flex; }\n.activity-btn[_ngcontent-%COMP%] { position: relative; }\n.activity-btn[_ngcontent-%COMP%] .activity-pulse[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n.activity-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 700;\n line-height: 16px;\n text-align: center;\n}\n.activity-drawer[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 320px;\n max-height: 420px;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 8px 28px color-mix(in srgb, var(--mj-text-primary) 18%, transparent);\n z-index: 1000;\n overflow: hidden;\n}\n.activity-drawer-head[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-weight: 700;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n.activity-clear[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 0.8rem;\n padding: 4px 6px;\n border-radius: 6px;\n}\n.activity-clear[_ngcontent-%COMP%]:hover { color: var(--mj-text-primary); background: var(--mj-bg-surface-hover); }\n.activity-list[_ngcontent-%COMP%] { overflow-y: auto; padding: 6px; }\n.activity-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 10px;\n padding: 9px 8px;\n border-radius: 8px;\n}\n.activity-row[_ngcontent-%COMP%]:hover { background: var(--mj-bg-surface-hover); }\n.activity-row-icon[_ngcontent-%COMP%] { margin-top: 2px; color: var(--mj-brand-primary); font-size: 0.85rem; }\n.activity-row.is-error[_ngcontent-%COMP%] .activity-row-icon[_ngcontent-%COMP%] { color: var(--mj-status-error); }\n.activity-row-body[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n.activity-row-label[_ngcontent-%COMP%] { font-size: 0.82rem; font-weight: 600; color: var(--mj-text-primary); }\n.activity-row-detail[_ngcontent-%COMP%] { font-size: 0.72rem; color: var(--mj-text-muted); margin-top: 1px; }\n.activity-bar[_ngcontent-%COMP%] {\n margin-top: 6px;\n height: 4px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 2px;\n overflow: hidden;\n}\n.activity-bar-fill[_ngcontent-%COMP%] { height: 100%; background: var(--mj-brand-primary); transition: width 0.3s ease; }"] });
|
|
3234
3464
|
}
|
|
3235
3465
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ShellComponent, [{
|
|
3236
3466
|
type: Component,
|
|
3237
|
-
args: [{ standalone: false, selector: 'mj-shell', template: "<div class=\"shell-container\" [class.hidden]=\"loading\" [class.tabs-visible]=\"tabBarVisible\">\n <!-- Header -->\n <header class=\"shell-header\">\n <!-- MJ Logo -->\n <div class=\"mj-logo\" title=\"MemberJunction\"></div>\n\n <!-- Mobile Hamburger Button -->\n <button class=\"hamburger-btn\" (click)=\"toggleMobileNav()\" title=\"Menu\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n <!-- Nav Bar Apps: Left of App Switcher -->\n @if (leftOfSwitcherApps.length > 0 && !appSwitchingLocked) {\n <div class=\"nav-bar-apps left-of-switcher\">\n @for (app of leftOfSwitcherApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <!-- App Switcher (hidden for app-locked sessions, e.g. magic-link) -->\n @if (!appSwitchingLocked) {\n <mj-app-switcher\n [activeApp]=\"activeApp\"\n [isViewingSystemTab]=\"isViewingSystemTab\"\n [loadingAppId]=\"loadingAppId\"\n (appSelected)=\"onAppSwitch($event)\">\n </mj-app-switcher>\n }\n\n <!-- App Navigation (desktop only) -->\n @if (activeApp) {\n <mj-app-nav\n class=\"desktop-nav\"\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n }\n\n <!-- Universal Search Bar -->\n @if (ShowSearchBar) {\n <div class=\"shell-search-bar desktop-only\">\n <mj-search-composite\n #shellSearchComposite\n Placeholder=\"Search everything...\"\n [ShowShortcutHint]=\"true\"\n [EnablePreview]=\"ShowSearchPreview\"\n [EnableRecent]=\"true\"\n [MaxPreviewResults]=\"8\"\n (ResultSelected)=\"OnSearchResultSelected($event)\"\n (SearchSubmitted)=\"OnSearchSubmitted($event)\"\n (SeeAllRequested)=\"OnSeeAllSearch($event)\">\n </mj-search-composite>\n </div>\n }\n <!-- Spacer -->\n <div class=\"spacer\"></div>\n <!-- Actions (activity, notifications, user menu) -->\n <div class=\"header-actions\">\n <!-- Global Activity indicator -->\n @if (activityItems.length > 0) {\n <div class=\"activity-wrap\">\n <button class=\"icon-btn desktop-only activity-btn\" title=\"Activity\" (click)=\"toggleActivity($event)\">\n <i class=\"fa-solid fa-wave-square\" [class.activity-pulse]=\"activityRunningCount > 0\"></i>\n @if (activityRunningCount > 0) {\n <span class=\"activity-badge\">{{ activityRunningCount }}</span>\n }\n </button>\n @if (activityOpen) {\n <div class=\"activity-drawer\" (click)=\"$event.stopPropagation()\">\n <div class=\"activity-drawer-head\">\n <span>Activity</span>\n <button class=\"activity-clear\" (click)=\"clearFinishedActivity()\" title=\"Clear finished\">\n <i class=\"fa-solid fa-broom\"></i>\n </button>\n </div>\n <div class=\"activity-list\">\n @for (a of activityItems; track a.ID) {\n <div class=\"activity-row\" [class.is-error]=\"a.Status === 'error'\">\n <i class=\"activity-row-icon\"\n [class]=\"a.Status === 'running' ? 'fa-solid fa-spinner fa-spin'\n : a.Status === 'error' ? 'fa-solid fa-circle-exclamation'\n : 'fa-solid fa-circle-check'\"></i>\n <div class=\"activity-row-body\">\n <div class=\"activity-row-label\">{{ a.Label }}</div>\n @if (a.Detail) { <div class=\"activity-row-detail\">{{ a.Detail }}</div> }\n @if (a.Status === 'running' && a.Progress != null) {\n <div class=\"activity-bar\"><div class=\"activity-bar-fill\" [style.width.%]=\"a.Progress\"></div></div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <button class=\"icon-btn desktop-only notification-btn\" title=\"Notifications\" (click)=\"showNotifications()\">\n <i class=\"fa-solid fa-bell\"></i>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n <!-- Nav Bar Apps: Left of User Menu -->\n @if (leftOfUserMenuApps.length > 0) {\n <div class=\"nav-bar-apps left-of-user-menu\">\n @for (app of leftOfUserMenuApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"user-menu\">\n <button class=\"avatar-btn\" (click)=\"toggleUserMenu($event)\">\n @if (userImageURL) {\n <img [src]=\"userImageURL\" alt=\"User avatar\" class=\"avatar-img\" />\n } @else {\n <div class=\"icon-fallback\">\n <i [class]=\"userIconClass || 'fa-solid fa-user'\"></i>\n </div>\n }\n </button>\n <!-- User Context Menu (Dynamic) -->\n @if (userMenuVisible) {\n <div class=\"user-context-menu\"\n [class.menu-fade]=\"getUserMenuOptions()?.animationStyle === 'fade'\"\n [class.menu-slide]=\"getUserMenuOptions()?.animationStyle === 'slide'\">\n <!-- User Header -->\n @if (getUserMenuOptions()?.showUserName) {\n <div class=\"user-menu-header\">\n <div class=\"user-info\">\n <span class=\"user-name\">{{ getUserDisplayInfo()?.name || userName }}</span>\n @if (getUserMenuOptions()?.showUserEmail && getUserDisplayInfo()?.email) {\n <span class=\"user-email\">\n {{ getUserDisplayInfo()?.email }}\n </span>\n }\n @if (getUserDisplayInfo()?.subtitle) {\n <span class=\"user-subtitle\">{{ getUserDisplayInfo()?.subtitle }}</span>\n }\n </div>\n </div>\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Dynamic Menu Items -->\n @for (element of userMenuElements; track element) {\n <!-- Divider -->\n @if (isMenuDivider(element)) {\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Menu Item -->\n @if (!isMenuDivider(element)) {\n @if (asMenuItem(element); as item) {\n @if (item.id === 'toggle-theme') {\n <div class=\"user-menu-item theme-toggle-item\"\n [title]=\"item.tooltip || ''\"\n (click)=\"onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n <div class=\"theme-toggle-track\" [class.dark]=\"IsDarkMode\">\n <div class=\"theme-toggle-thumb\">\n <i [class]=\"IsDarkMode ? 'fa-solid fa-moon' : 'fa-solid fa-sun'\" class=\"theme-toggle-icon\"></i>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"user-menu-item\"\n [class.disabled]=\"!item.enabled\"\n [class.danger]=\"item.cssClass === 'danger'\"\n [style.color]=\"item.color || null\"\n [title]=\"item.tooltip || ''\"\n (click)=\"item.enabled && onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n @if (item.shortcut) {\n <span class=\"menu-shortcut\">{{ item.shortcut }}</span>\n }\n </div>\n }\n }\n }\n }\n </div>\n }\n </div>\n </div>\n </header>\n\n <!-- Search Popup -->\n @if (isSearchOpen) {\n <div class=\"search-popup-overlay\" (click)=\"closeSearch()\"></div>\n }\n <div class=\"search-popup\" [class.open]=\"isSearchOpen\">\n <div class=\"search-popup-content\" (click)=\"$event.stopPropagation()\">\n <mj-dropdown\n [Data]=\"searchableEntities\"\n TextField=\"Name\"\n ValueField=\"ID\"\n class=\"search-entity-dropdown\"\n [(ngModel)]=\"selectedEntity\">\n </mj-dropdown>\n <input\n type=\"text\"\n #searchInput\n placeholder=\"Search...\"\n class=\"mj-input search-input\"\n (keydown.enter)=\"onSearch($event)\"\n />\n <button class=\"search-submit-btn\" (click)=\"onSearch($event)\" title=\"Search\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n </div>\n </div>\n\n <!-- Mobile Navigation Drawer -->\n @if (mobileNavOpen) {\n <div class=\"mobile-nav-overlay\" (click)=\"closeMobileNav()\"></div>\n }\n <div class=\"mobile-nav-drawer\" [class.open]=\"mobileNavOpen\">\n <div class=\"mobile-nav-header\">\n <span>Navigation</span>\n <button class=\"close-btn\" (click)=\"closeMobileNav()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (activeApp) {\n <div class=\"mobile-nav-content\">\n <div class=\"mobile-nav-section-title\">{{ activeApp.Name }}</div>\n <mj-app-nav\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n </div>\n }\n <div class=\"mobile-nav-footer\">\n <button class=\"mobile-nav-action\" title=\"Search\" (click)=\"toggleSearch(); closeMobileNav()\">\n <i class=\"fa-solid fa-search\"></i>\n <span>Search</span>\n </button>\n <button class=\"mobile-nav-action\" title=\"Notifications\" (click)=\"showNotifications(); closeMobileNav()\">\n <i class=\"fa-solid fa-bell\"></i>\n <span>Notifications</span>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge-mobile\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n </div>\n </div>\n\n <!-- Tab Container - with dynamic tab bar visibility -->\n <mj-tab-container\n [class.hide-tab-bar]=\"!tabBarVisible\"\n (firstResourceLoadComplete)=\"onFirstResourceLoadComplete()\"\n (layoutInitError)=\"handleLayoutError()\">\n </mj-tab-container>\n</div>\n\n<!-- Loading State -->\n@if (loading) {\n <div class=\"shell-loading\">\n <mj-loading\n [text]=\"currentLoadingText\"\n [textColor]=\"currentLoadingTextColor\"\n [logoColor]=\"currentLoadingColor\"\n [logoGradient]=\"currentLoadingGradient\"\n [animation]=\"currentLoadingAnimation\"\n size=\"large\">\n </mj-loading>\n @if (ShowResetOption) {\n <div class=\"loading-reset-panel\">\n <p class=\"loading-reset-message\">\n <i class=\"fa-regular fa-clock\"></i>\n Taking longer than expected\n </p>\n <p class=\"loading-reset-hint\">\n This can happen after updates or due to cached data issues.\n </p>\n <button class=\"loading-reset-btn\" (click)=\"ResetApplication()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Reset\n </button>\n </div>\n } @else {\n <div class=\"loading-version\">MemberJunction \u00B7 v{{ MJVersion }}</div>\n }\n </div>\n}\n\n<!-- App Access Error Dialog -->\n<mj-app-access-dialog\n #appAccessDialog\n (result)=\"onAppAccessDialogResult($event)\">\n</mj-app-access-dialog>\n\n<!-- Command Palette -->\n<mj-command-palette (AppSelected)=\"onAppSwitch($event)\"></mj-command-palette>\n\n<!-- Pin Progress Overlay -->\n@if (PinProgressVisible) {\n <div class=\"pin-progress-backdrop\">\n <div class=\"pin-progress-modal\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span class=\"pin-progress-text\">{{ PinProgressText }}</span>\n </div>\n </div>\n}\n", styles: [":host {\n display: block;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n/* MJ Logo - uses design token for theme switching & white-labeling */\n.mj-logo {\n width: 32px;\n height: 18px;\n background-image: var(--mj-logo-mark);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n flex-shrink: 0;\n}\n\n.shell-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: relative;\n}\n\n/* Hide shell container while loading - allows tab container to render and load\n first resource in background while shell loading indicator is visible */\n.shell-container.hidden {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n/* Hide Golden Layout tab headers when only one tab */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_header {\n display: none;\n}\n\n/* Show tab headers when multiple tabs */\nmj-tab-container:not(.hide-tab-bar) ::ng-deep .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n/* Adjust content area height when tabs hidden */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_content {\n height: 100% !important;\n}\n\n/* Ensure smooth transitions */\nmj-tab-container ::ng-deep .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n /* Creates a stacking context so children (search bar z-index: 99999, dropdown)\n are contained within this level. Modal overlays (z-index: 1000+) sit above. */\n position: relative;\n z-index: 500;\n}\n\n/* Nav Bar Apps - permanent app icons in the header */\n.nav-bar-apps {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher {\n /* No extra margin - header gap handles spacing */\n /* This prevents the app switcher from shifting when icons are hidden */\n}\n\n.nav-bar-apps.left-of-user-menu {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn i {\n transition: transform 0.15s ease;\n margin-top: 2px; /* Align with app switcher icon */\n}\n\n.nav-bar-app-btn:hover i {\n transform: scale(1.1);\n}\n\n.spacer {\n flex: 1;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Notification button with badge */\n.notification-btn {\n position: relative;\n}\n\n.notification-badge {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu {\n position: relative;\n}\n\n.user-menu .avatar-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu .avatar-btn:hover {\n transform: scale(1.05);\n}\n\n/* Icon fallback styling - shows gray circle with icon */\n.user-menu .avatar-btn .icon-fallback {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu .avatar-btn:hover .icon-fallback {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu .avatar-btn .icon-fallback i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n/* Avatar image - replaces the gray circle entirely */\n.user-menu .avatar-btn .avatar-img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu .avatar-btn:hover .avatar-img {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n/* User Menu Header */\n.user-menu-header {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header .user-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header .user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header .user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header .user-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* User Context Menu */\n.user-context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item i {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger i {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Menu item disabled state */\n.user-menu-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled:hover {\n background: transparent;\n}\n\n/* Theme Toggle Switch */\n.theme-toggle-item {\n cursor: pointer;\n}\n\n.theme-toggle-track {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark .theme-toggle-thumb {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark .theme-toggle-icon {\n color: var(--mj-text-inverse);\n}\n\n/* Menu shortcut hint */\n.user-menu-item .menu-shortcut {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n/* Menu animations */\n.user-context-menu.menu-fade {\n animation: menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide {\n animation: menuSlideIn 0.2s ease-out;\n}\n\n@keyframes menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n z-index: 99999;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n.loading-version {\n margin-top: var(--mj-space-8, 24px);\n font-size: 11px;\n color: var(--mj-text-muted);\n letter-spacing: 0.4px;\n opacity: 0.6;\n user-select: none;\n}\n\n/* Loading Recovery Reset Panel */\n.loading-reset-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message i {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn i {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Hamburger button - hidden on desktop */\n.hamburger-btn {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Mobile Navigation Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n/* Mobile Navigation Drawer */\n.mobile-nav-drawer {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open {\n transform: translateX(0);\n}\n\n.mobile-nav-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header span {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header .close-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action {\n position: relative;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n/* Mobile Responsive Styles */\n@media (max-width: 768px) {\n .hamburger-btn {\n display: flex;\n }\n\n .desktop-nav {\n display: none !important;\n }\n\n .desktop-only {\n display: none !important;\n }\n\n .mobile-nav-overlay {\n display: block;\n }\n\n .mobile-nav-drawer {\n display: flex;\n }\n\n .shell-header {\n padding: 0 12px;\n gap: 8px;\n }\n\n /* Keep the right-edge cluster (chat/nav-bar app icons + avatar) on one row.\n Without pinning this, the icons can wrap and the avatar drops onto a second\n line, stacking under the chat icon. */\n .header-actions {\n flex-direction: row;\n flex-wrap: nowrap;\n }\n .header-actions .user-menu,\n .header-actions .nav-bar-apps {\n flex-shrink: 0;\n }\n}\n\n/* Settings Full-Screen Window Styles */\n::ng-deep .settings-fullscreen-window {\n /* Remove window chrome for full-screen feel */\n box-shadow: none !important;\n border: none !important;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n/* Hide minimize/maximize buttons - only show close */\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n/* ========================================\n UNIVERSAL SEARCH BAR\n ======================================== */\n.shell-search-bar {\n flex: 0 1 420px;\n min-width: 200px;\n max-width: 520px;\n margin: 0 12px;\n position: relative;\n z-index: 99999;\n}\n@media (max-width: 768px) {\n .shell-search-bar { display: none; }\n}\n\n/* ========================================\n SEARCH POPUP\n ======================================== */\n\n.search-popup-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup {\n position: absolute;\n top: 60px; /* Below header */\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn:active {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Mobile notification badge */\n.notification-badge-mobile {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Mobile-specific search popup adjustments */\n@media (max-width: 768px) {\n .search-popup {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown {\n width: 100%;\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ========================================\n PIN PROGRESS OVERLAY\n ======================================== */\n.pin-progress-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: pinBackdropIn 0.2s ease;\n}\n\n@keyframes pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: pinModalIn 0.25s ease;\n}\n\n@keyframes pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n/* ============================================================\n Global Activity indicator (P3)\n ============================================================ */\n.activity-wrap { position: relative; display: inline-flex; }\n.activity-btn { position: relative; }\n.activity-btn .activity-pulse { color: var(--mj-brand-primary); }\n.activity-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 700;\n line-height: 16px;\n text-align: center;\n}\n.activity-drawer {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 320px;\n max-height: 420px;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 8px 28px color-mix(in srgb, var(--mj-text-primary) 18%, transparent);\n z-index: 1000;\n overflow: hidden;\n}\n.activity-drawer-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-weight: 700;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n.activity-clear {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 0.8rem;\n padding: 4px 6px;\n border-radius: 6px;\n}\n.activity-clear:hover { color: var(--mj-text-primary); background: var(--mj-bg-surface-hover); }\n.activity-list { overflow-y: auto; padding: 6px; }\n.activity-row {\n display: flex;\n gap: 10px;\n padding: 9px 8px;\n border-radius: 8px;\n}\n.activity-row:hover { background: var(--mj-bg-surface-hover); }\n.activity-row-icon { margin-top: 2px; color: var(--mj-brand-primary); font-size: 0.85rem; }\n.activity-row.is-error .activity-row-icon { color: var(--mj-status-error); }\n.activity-row-body { flex: 1; min-width: 0; }\n.activity-row-label { font-size: 0.82rem; font-weight: 600; color: var(--mj-text-primary); }\n.activity-row-detail { font-size: 0.72rem; color: var(--mj-text-muted); margin-top: 1px; }\n.activity-bar {\n margin-top: 6px;\n height: 4px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 2px;\n overflow: hidden;\n}\n.activity-bar-fill { height: 100%; background: var(--mj-brand-primary); transition: width 0.3s ease; }\n"] }]
|
|
3467
|
+
args: [{ standalone: false, selector: 'mj-shell', template: "<div class=\"shell-container\" [class.hidden]=\"loading\" [class.tabs-visible]=\"tabBarVisible\">\n <!-- Header -->\n <header class=\"shell-header\">\n <!-- MJ Logo -->\n <div class=\"mj-logo\" title=\"MemberJunction\"></div>\n\n <!-- Mobile Hamburger Button -->\n <button class=\"hamburger-btn\" (click)=\"toggleMobileNav()\" title=\"Menu\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n <!-- Nav Bar Apps: Left of App Switcher -->\n @if (leftOfSwitcherApps.length > 0 && !appSwitchingLocked) {\n <div class=\"nav-bar-apps left-of-switcher\">\n @for (app of leftOfSwitcherApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <!-- App Switcher (hidden for app-locked sessions, e.g. magic-link, and\n removable per deployment via 'Shell.AppSwitcher.Enabled') -->\n @if (!appSwitchingLocked && ShowAppSwitcher) {\n <mj-app-switcher\n [activeApp]=\"activeApp\"\n [isViewingSystemTab]=\"isViewingSystemTab\"\n [loadingAppId]=\"loadingAppId\"\n (appSelected)=\"onAppSwitch($event)\">\n </mj-app-switcher>\n }\n\n <!-- App Navigation (desktop only; removable per deployment via 'Shell.AppNav.Enabled') -->\n @if (activeApp && ShowAppNav) {\n <mj-app-nav\n class=\"desktop-nav\"\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n }\n\n <!-- Spacer -->\n <div class=\"spacer\"></div>\n <!-- Actions (activity, notifications, user menu) -->\n <div class=\"header-actions\">\n <!-- Universal Search \u2014 right-anchored with the action cluster, static width\n (2026-07 review consensus: visible when space permits, never resizes).\n Omnibar ON: a button styled as an input \u2014 clicking (or Ctrl/Cmd+K) opens\n the modal palette; typing happens there. Collapses to the icon circle at\n the mobile breakpoint.\n Omnibar OFF: a REAL inline input (mj-search-composite) \u2014 results attach\n beneath it as a suggest dropdown with a \"See all results\" footer. On\n mobile the composite hides and an icon button opens the Spotlight\n overlay instead (same slot, same collapse point). -->\n @if (ShowSearchBar) {\n @if (UseOmnibar) {\n <button class=\"search-btn\" title=\"Search everything\"\n [attr.aria-label]=\"'Search everything (' + OmnibarShortcutLabel + ')'\"\n (click)=\"OnHeaderSearchClick()\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n <span class=\"search-btn-text desktop-only\">Search everything</span>\n <kbd class=\"search-btn-kbd desktop-only\" aria-hidden=\"true\">{{ OmnibarShortcutLabel }}</kbd>\n </button>\n } @else {\n <div class=\"shell-search-bar desktop-only\">\n <mj-search-composite\n #shellSearchComposite\n Placeholder=\"Search everything...\"\n [ShowShortcutHint]=\"true\"\n [EnablePreview]=\"ShowSearchPreview\"\n [EnableRecent]=\"true\"\n [MaxPreviewResults]=\"8\"\n [ShowPromo]=\"ShowOmnibarPromo\"\n [PromoText]=\"OmnibarPromoText\"\n (ResultSelected)=\"OnSearchResultSelected($event)\"\n (SearchSubmitted)=\"OnSearchSubmitted($event)\"\n (SeeAllRequested)=\"OnSeeAllSearch($event)\"\n (RecentRecordSelected)=\"OnSearchResultSelected($event)\"\n (PromoAccepted)=\"OnOmnibarPromoAccepted($event)\"\n (PromoDismissed)=\"OnOmnibarPromoDismissed()\">\n </mj-search-composite>\n </div>\n <button class=\"search-btn search-btn-mobile\" title=\"Search everything\"\n [attr.aria-label]=\"'Search everything (' + OmnibarShortcutLabel + ')'\"\n (click)=\"OnHeaderSearchClick()\">\n <i class=\"fa-solid fa-magnifying-glass\"></i>\n </button>\n }\n }\n <!-- Global Activity indicator -->\n @if (activityItems.length > 0) {\n <div class=\"activity-wrap\">\n <button class=\"icon-btn desktop-only activity-btn\" title=\"Activity\" (click)=\"toggleActivity($event)\">\n <i class=\"fa-solid fa-wave-square\" [class.activity-pulse]=\"activityRunningCount > 0\"></i>\n @if (activityRunningCount > 0) {\n <span class=\"activity-badge\">{{ activityRunningCount }}</span>\n }\n </button>\n @if (activityOpen) {\n <div class=\"activity-drawer\" (click)=\"$event.stopPropagation()\">\n <div class=\"activity-drawer-head\">\n <span>Activity</span>\n <button class=\"activity-clear\" (click)=\"clearFinishedActivity()\" title=\"Clear finished\">\n <i class=\"fa-solid fa-broom\"></i>\n </button>\n </div>\n <div class=\"activity-list\">\n @for (a of activityItems; track a.ID) {\n <div class=\"activity-row\" [class.is-error]=\"a.Status === 'error'\">\n <i class=\"activity-row-icon\"\n [class]=\"a.Status === 'running' ? 'fa-solid fa-spinner fa-spin'\n : a.Status === 'error' ? 'fa-solid fa-circle-exclamation'\n : 'fa-solid fa-circle-check'\"></i>\n <div class=\"activity-row-body\">\n <div class=\"activity-row-label\">{{ a.Label }}</div>\n @if (a.Detail) { <div class=\"activity-row-detail\">{{ a.Detail }}</div> }\n @if (a.Status === 'running' && a.Progress != null) {\n <div class=\"activity-bar\"><div class=\"activity-bar-fill\" [style.width.%]=\"a.Progress\"></div></div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n @if (ShowNotifications) {\n <button class=\"icon-btn desktop-only notification-btn\" title=\"Notifications\" (click)=\"showNotifications()\">\n <i class=\"fa-solid fa-bell\"></i>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n }\n <!-- Nav Bar Apps: Left of User Menu -->\n @if (leftOfUserMenuApps.length > 0) {\n <div class=\"nav-bar-apps left-of-user-menu\">\n @for (app of leftOfUserMenuApps; track app) {\n <button\n class=\"nav-bar-app-btn\"\n [class.active]=\"IsActiveApp(app)\"\n [title]=\"app.Name\"\n [style.--app-color]=\"app.GetColor()\"\n (click)=\"onNavBarAppClick(app, $event)\"\n (dblclick)=\"onNavBarAppDblClick(app, $event)\">\n <i [class]=\"app.Icon\"></i>\n </button>\n }\n </div>\n }\n\n <div class=\"user-menu\">\n <button class=\"avatar-btn\" (click)=\"toggleUserMenu($event)\">\n @if (userImageURL) {\n <img [src]=\"userImageURL\" alt=\"User avatar\" class=\"avatar-img\" />\n } @else {\n <div class=\"icon-fallback\">\n <i [class]=\"userIconClass || 'fa-solid fa-user'\"></i>\n </div>\n }\n </button>\n <!-- User Context Menu (Dynamic) -->\n @if (userMenuVisible) {\n <div class=\"user-context-menu\"\n [class.menu-fade]=\"getUserMenuOptions()?.animationStyle === 'fade'\"\n [class.menu-slide]=\"getUserMenuOptions()?.animationStyle === 'slide'\">\n <!-- User Header -->\n @if (getUserMenuOptions()?.showUserName) {\n <div class=\"user-menu-header\">\n <div class=\"user-info\">\n <span class=\"user-name\">{{ getUserDisplayInfo()?.name || userName }}</span>\n @if (getUserMenuOptions()?.showUserEmail && getUserDisplayInfo()?.email) {\n <span class=\"user-email\">\n {{ getUserDisplayInfo()?.email }}\n </span>\n }\n @if (getUserDisplayInfo()?.subtitle) {\n <span class=\"user-subtitle\">{{ getUserDisplayInfo()?.subtitle }}</span>\n }\n </div>\n </div>\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Dynamic Menu Items -->\n @for (element of userMenuElements; track element) {\n <!-- Divider -->\n @if (isMenuDivider(element)) {\n <div class=\"user-menu-divider\"></div>\n }\n <!-- Menu Item -->\n @if (!isMenuDivider(element)) {\n @if (asMenuItem(element); as item) {\n @if (item.id === 'toggle-theme') {\n <div class=\"user-menu-item theme-toggle-item\"\n [title]=\"item.tooltip || ''\"\n (click)=\"onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n <div class=\"theme-toggle-track\" [class.dark]=\"IsDarkMode\">\n <div class=\"theme-toggle-thumb\">\n <i [class]=\"IsDarkMode ? 'fa-solid fa-moon' : 'fa-solid fa-sun'\" class=\"theme-toggle-icon\"></i>\n </div>\n </div>\n </div>\n } @else {\n <div class=\"user-menu-item\"\n [class.disabled]=\"!item.enabled\"\n [class.danger]=\"item.cssClass === 'danger'\"\n [style.color]=\"item.color || null\"\n [title]=\"item.tooltip || ''\"\n (click)=\"item.enabled && onUserMenuItemClick(item.id)\">\n <i [class]=\"item.icon\"></i>\n <span class=\"menu-label\">{{ item.label }}</span>\n @if (item.shortcut) {\n <span class=\"menu-shortcut\">{{ item.shortcut }}</span>\n }\n </div>\n }\n }\n }\n }\n </div>\n }\n </div>\n </div>\n </header>\n\n <!-- Search Popup -->\n @if (isSearchOpen) {\n <div class=\"search-popup-overlay\" (click)=\"closeSearch()\"></div>\n }\n <div class=\"search-popup\" [class.open]=\"isSearchOpen\">\n <div class=\"search-popup-content\" (click)=\"$event.stopPropagation()\">\n <mj-dropdown\n [Data]=\"searchableEntities\"\n TextField=\"Name\"\n ValueField=\"ID\"\n class=\"search-entity-dropdown\"\n [(ngModel)]=\"selectedEntity\">\n </mj-dropdown>\n <input\n type=\"text\"\n #searchInput\n placeholder=\"Search...\"\n class=\"mj-input search-input\"\n (keydown.enter)=\"onSearch($event)\"\n />\n <button class=\"search-submit-btn\" (click)=\"onSearch($event)\" title=\"Search\">\n <i class=\"fa-solid fa-search\"></i>\n </button>\n </div>\n </div>\n\n <!-- Mobile Navigation Drawer -->\n @if (mobileNavOpen) {\n <div class=\"mobile-nav-overlay\" (click)=\"closeMobileNav()\"></div>\n }\n <div class=\"mobile-nav-drawer\" [class.open]=\"mobileNavOpen\">\n <div class=\"mobile-nav-header\">\n <span>Navigation</span>\n <button class=\"close-btn\" (click)=\"closeMobileNav()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n @if (activeApp && ShowAppNav) {\n <div class=\"mobile-nav-content\">\n <div class=\"mobile-nav-section-title\">{{ activeApp.Name }}</div>\n <mj-app-nav\n [app]=\"activeApp\"\n (navItemClick)=\"onNavItemClick($event)\"\n (navItemDismiss)=\"onNavItemDismiss($event)\">\n </mj-app-nav>\n </div>\n }\n <div class=\"mobile-nav-footer\">\n <button class=\"mobile-nav-action\" title=\"Search\" (click)=\"toggleSearch(); closeMobileNav()\">\n <i class=\"fa-solid fa-search\"></i>\n <span>Search</span>\n </button>\n @if (ShowNotifications) {\n <button class=\"mobile-nav-action\" title=\"Notifications\" (click)=\"showNotifications(); closeMobileNav()\">\n <i class=\"fa-solid fa-bell\"></i>\n <span>Notifications</span>\n @if (unreadNotificationCount > 0) {\n <span class=\"notification-badge-mobile\">\n {{ unreadNotificationCount > 99 ? '99+' : unreadNotificationCount }}\n </span>\n }\n </button>\n }\n </div>\n </div>\n\n <!-- Tab Container - with dynamic tab bar visibility -->\n <mj-tab-container\n [class.hide-tab-bar]=\"!tabBarVisible\"\n (firstResourceLoadComplete)=\"onFirstResourceLoadComplete()\"\n (layoutInitError)=\"handleLayoutError()\">\n </mj-tab-container>\n</div>\n\n<!-- Loading State -->\n@if (loading) {\n <div class=\"shell-loading\">\n <mj-loading\n [text]=\"currentLoadingText\"\n [textColor]=\"currentLoadingTextColor\"\n [logoColor]=\"currentLoadingColor\"\n [logoGradient]=\"currentLoadingGradient\"\n [animation]=\"currentLoadingAnimation\"\n size=\"large\">\n </mj-loading>\n @if (ShowResetOption) {\n <div class=\"loading-reset-panel\">\n <p class=\"loading-reset-message\">\n <i class=\"fa-regular fa-clock\"></i>\n Taking longer than expected\n </p>\n <p class=\"loading-reset-hint\">\n This can happen after updates or due to cached data issues.\n </p>\n <button class=\"loading-reset-btn\" (click)=\"ResetApplication()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n Reset\n </button>\n </div>\n } @else {\n <div class=\"loading-version\">MemberJunction \u00B7 v{{ MJVersion }}</div>\n }\n </div>\n}\n\n<!-- App Access Error Dialog -->\n<mj-app-access-dialog\n #appAccessDialog\n (result)=\"onAppAccessDialogResult($event)\">\n</mj-app-access-dialog>\n\n<!-- Command Palette -->\n<mj-command-palette (AppSelected)=\"onAppSwitch($event)\"></mj-command-palette>\n\n<!-- Unified command palette (Shell.Omnibar.Enabled) -->\n<mj-omnibar-palette #omnibarPalette (SettingsRequested)=\"OnPaletteSettingsRequested()\"></mj-omnibar-palette>\n\n<!-- Legacy universal search as a Spotlight-style overlay \u2014 omnibar-off MOBILE only\n (on desktop the inline header composite owns the experience; this opens from\n the mobile icon or Ctrl/Cmd+K when the composite isn't visible).\n The shell owns the Ctrl/Cmd+K chord, so the overlay's own global shortcut is off. -->\n@if (ShowSearchBar && !UseOmnibar) {\n <mj-search-overlay\n [(IsOpen)]=\"LegacySearchOpen\"\n Placeholder=\"Search everything...\"\n [EnableGlobalShortcut]=\"false\"\n [ShowPromo]=\"ShowOmnibarPromo\"\n [PromoText]=\"OmnibarPromoText\"\n (ResultSelected)=\"OnOverlayResultSelected($event)\"\n (SeeAllRequested)=\"OnOverlaySeeAll($event)\"\n (PromoAccepted)=\"OnOmnibarPromoAccepted($event)\"\n (PromoDismissed)=\"OnOmnibarPromoDismissed()\">\n </mj-search-overlay>\n}\n\n<!-- Pin Progress Overlay -->\n@if (PinProgressVisible) {\n <div class=\"pin-progress-backdrop\">\n <div class=\"pin-progress-modal\">\n <mj-loading [showText]=\"false\" size=\"small\"></mj-loading>\n <span class=\"pin-progress-text\">{{ PinProgressText }}</span>\n </div>\n </div>\n}\n", styles: [":host {\n display: block;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n/* MJ Logo - uses design tokens for theme switching & white-labeling.\n Geometry follows --mj-logo-width/-height so a differently-shaped org mark fits;\n --mj-logo-plate-bg is set by the theme engine only when a single-variant logo needs\n a legibility plate in the mode it wasn't designed for (org-theming Phase 4). */\n.mj-logo {\n width: var(--mj-logo-width, 32px);\n height: var(--mj-logo-height, 18px);\n background-image: var(--mj-logo-mark);\n background-color: var(--mj-logo-plate-bg, transparent);\n background-repeat: no-repeat;\n background-position: center;\n background-size: contain;\n border-radius: var(--mj-radius-sm, 4px);\n flex-shrink: 0;\n}\n\n.shell-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n position: relative;\n}\n\n/* Hide shell container while loading - allows tab container to render and load\n first resource in background while shell loading indicator is visible */\n.shell-container.hidden {\n visibility: hidden;\n position: absolute;\n pointer-events: none;\n}\n\nmj-tab-container {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n transition: all 0.2s ease-in-out;\n}\n\n/* Hide Golden Layout tab headers when only one tab */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_header {\n display: none;\n}\n\n/* Show tab headers when multiple tabs */\nmj-tab-container:not(.hide-tab-bar) ::ng-deep .lm_header {\n opacity: 1;\n max-height: 40px;\n transition: opacity 0.2s ease-in-out, max-height 0.2s ease-in-out;\n}\n\n/* Adjust content area height when tabs hidden */\nmj-tab-container.hide-tab-bar ::ng-deep .lm_content {\n height: 100% !important;\n}\n\n/* Ensure smooth transitions */\nmj-tab-container ::ng-deep .lm_stack {\n transition: all 0.2s ease-in-out;\n}\n\n.shell-header {\n height: 60px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 16px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n /* Creates a stacking context so children (search bar z-index: 99999, dropdown)\n are contained within this level. Modal overlays (z-index: 1000+) sit above. */\n position: relative;\n z-index: 500;\n}\n\n/* Nav Bar Apps - permanent app icons in the header */\n.nav-bar-apps {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.nav-bar-apps.left-of-switcher {\n /* No extra margin - header gap handles spacing */\n /* This prevents the app switcher from shifting when icons are hidden */\n}\n\n.nav-bar-apps.left-of-user-menu {\n margin-right: 8px;\n}\n\n.nav-bar-app-btn {\n --app-color: var(--mj-text-muted);\n width: 40px;\n height: 40px;\n border-radius: 10px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 18px;\n transition: all 0.15s ease;\n position: relative;\n}\n\n.nav-bar-app-btn:hover {\n background: color-mix(in srgb, var(--app-color) 15%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active {\n background: color-mix(in srgb, var(--app-color) 20%, transparent);\n color: var(--app-color);\n}\n\n.nav-bar-app-btn.active::after {\n content: '';\n position: absolute;\n bottom: 6px;\n left: 50%;\n transform: translateX(-50%);\n width: 16px;\n height: 3px;\n background: var(--app-color);\n border-radius: 2px;\n}\n\n.nav-bar-app-btn i {\n transition: transform 0.15s ease;\n margin-top: 2px; /* Align with app switcher icon */\n}\n\n.nav-bar-app-btn:hover i {\n transform: scale(1.1);\n}\n\n.spacer {\n flex: 1;\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.icon-btn {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n\n.icon-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Universal search: a static-width bar styled as an input, anchored on the\n right with the action cluster. Deliberately NOT resizable on hover/focus \u2014\n chrome that shifts on interaction was rejected in the 2026-07 review. It's a\n button (typing happens in the overlay it opens), so no focus/caret styling. */\n.search-btn {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 260px;\n height: 36px;\n padding: 0 var(--mj-space-2-5) 0 var(--mj-space-3-5);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n font-size: var(--mj-text-sm);\n font-family: inherit;\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.search-btn:hover {\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n}\n\n.search-btn:focus-visible {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n/* Omnibar-off mobile trigger: hidden on desktop (the inline composite renders\n instead); the 768px block flips it on as the icon circle. */\n.search-btn-mobile {\n display: none;\n}\n\n/* Omnibar-off desktop: the inline search composite, same slot + width as the\n omnibar bar so the opt-in toggle doesn't move the header. */\n.shell-search-bar {\n position: relative;\n width: 260px;\n z-index: 99999;\n}\n\n/* The suggest dropdown needs more width than its 260px anchor. Pin it to the\n anchor's right edge and let it grow leftward \u2014 the bar is right-anchored, so\n leftward growth stays on screen. */\n.shell-search-bar ::ng-deep .suggest-dropdown {\n left: auto;\n right: 0;\n width: min(560px, calc(100vw - var(--mj-space-6)));\n}\n\n.search-btn i {\n font-size: var(--mj-text-sm);\n flex-shrink: 0;\n}\n\n.search-btn .search-btn-text {\n flex: 1;\n min-width: 0;\n text-align: left;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* kbd chip: deliberately mirrors the omnibar palette's .ob-kbd chrome\n (10.5px / 5px radius / bottom-heavy border) so the affordance and the\n surface it summons read as one system. */\n.search-btn .search-btn-kbd {\n flex-shrink: 0;\n white-space: nowrap;\n font-family: inherit;\n font-size: 10.5px;\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-bottom-width: 2px;\n border-radius: 5px;\n padding: 1.5px var(--mj-space-1-5);\n}\n\n/* Notification button with badge */\n.notification-btn {\n position: relative;\n}\n\n.notification-badge {\n position: absolute;\n top: 4px;\n right: 4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n.user-menu {\n position: relative;\n}\n\n.user-menu .avatar-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: box-shadow 0.15s, transform 0.15s;\n padding: 0;\n overflow: hidden;\n}\n\n.user-menu .avatar-btn:hover {\n transform: scale(1.05);\n}\n\n/* Icon fallback styling - shows gray circle with icon */\n.user-menu .avatar-btn .icon-fallback {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n border: 2px solid var(--mj-border-default);\n background: var(--mj-bg-surface-hover);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: border-color 0.15s;\n}\n\n.user-menu .avatar-btn:hover .icon-fallback {\n border-color: var(--mj-brand-primary);\n}\n\n.user-menu .avatar-btn .icon-fallback i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n/* Avatar image - replaces the gray circle entirely */\n.user-menu .avatar-btn .avatar-img {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n object-fit: cover;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);\n}\n\n.user-menu .avatar-btn:hover .avatar-img {\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\n}\n\n/* User Menu Header */\n.user-menu-header {\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n}\n\n.user-menu-header .user-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.user-menu-header .user-name {\n font-weight: 600;\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.user-menu-header .user-email {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.user-menu-header .user-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n font-style: italic;\n}\n\n/* User Context Menu */\n.user-context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 8px;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n min-width: 180px;\n z-index: 10000;\n overflow: hidden;\n}\n\n.user-menu-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n}\n\n.user-menu-item i {\n width: 18px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.user-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.user-menu-item.danger {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger i {\n color: var(--mj-status-error);\n}\n\n.user-menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface-elevated));\n}\n\n.user-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Menu item disabled state */\n.user-menu-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.user-menu-item.disabled:hover {\n background: transparent;\n}\n\n/* Theme Toggle Switch */\n.theme-toggle-item {\n cursor: pointer;\n}\n\n.theme-toggle-track {\n position: relative;\n width: 40px;\n height: 22px;\n border-radius: 11px;\n background: var(--mj-bg-surface-active);\n margin-left: auto;\n transition: background 0.2s ease;\n flex-shrink: 0;\n}\n\n.theme-toggle-track.dark {\n background: var(--mj-brand-primary);\n}\n\n.theme-toggle-thumb {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--mj-bg-surface);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease;\n}\n\n.theme-toggle-track.dark .theme-toggle-thumb {\n transform: translateX(18px);\n}\n\n.theme-toggle-icon {\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.theme-toggle-track.dark .theme-toggle-icon {\n color: var(--mj-text-inverse);\n}\n\n/* Menu shortcut hint */\n.user-menu-item .menu-shortcut {\n margin-left: auto;\n font-size: 11px;\n color: var(--mj-text-disabled);\n font-family: monospace;\n}\n\n/* Menu animations */\n.user-context-menu.menu-fade {\n animation: menuFadeIn 0.15s ease-out;\n}\n\n.user-context-menu.menu-slide {\n animation: menuSlideIn 0.2s ease-out;\n}\n\n@keyframes menuFadeIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes menuSlideIn {\n from {\n opacity: 0;\n transform: translateY(-16px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n.shell-loading {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n z-index: 99999;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding-bottom: 15vh;\n background: var(--mj-bg-page);\n}\n\n.loading-version {\n margin-top: var(--mj-space-8, 24px);\n font-size: 11px;\n color: var(--mj-text-muted);\n letter-spacing: 0.4px;\n opacity: 0.6;\n user-select: none;\n}\n\n/* Loading Recovery Reset Panel */\n.loading-reset-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--mj-space-3);\n margin-top: var(--mj-space-10);\n padding: var(--mj-space-8);\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n box-shadow: var(--mj-shadow-md);\n max-width: 420px;\n animation: resetPanelFadeIn 0.4s ease-out;\n}\n\n.loading-reset-message {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin: 0;\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.loading-reset-message i {\n font-size: var(--mj-text-lg);\n color: var(--mj-status-warning);\n}\n\n.loading-reset-hint {\n margin: 0;\n font-size: var(--mj-text-sm);\n color: var(--mj-text-secondary);\n text-align: center;\n line-height: var(--mj-leading-relaxed);\n}\n\n.loading-reset-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n margin-top: var(--mj-space-3);\n padding: var(--mj-space-3) var(--mj-space-6);\n font-size: var(--mj-text-base);\n font-weight: var(--mj-font-medium);\n font-family: var(--mj-font-family);\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: 1px solid var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n cursor: pointer;\n transition: var(--mj-transition-colors);\n}\n\n.loading-reset-btn:hover {\n background: var(--mj-brand-primary-hover);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary-hover);\n box-shadow: var(--mj-shadow-md);\n}\n\n.loading-reset-btn:active {\n background: var(--mj-brand-primary-active);\n color: var(--mj-text-inverse);\n transform: scale(0.98);\n}\n\n.loading-reset-btn i {\n font-size: var(--mj-text-sm);\n}\n\n@keyframes resetPanelFadeIn {\n from {\n opacity: 0;\n transform: translateY(12px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Hamburger button - hidden on desktop */\n.hamburger-btn {\n display: none;\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: none;\n cursor: pointer;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-secondary);\n font-size: 20px;\n transition: background 0.15s;\n}\n.hamburger-btn:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n/* Mobile Navigation Overlay */\n.mobile-nav-overlay {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 9998;\n}\n\n/* Mobile Navigation Drawer */\n.mobile-nav-drawer {\n display: none;\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n width: 280px;\n max-width: 85vw;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-xl);\n z-index: 9999;\n flex-direction: column;\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n}\n.mobile-nav-drawer.open {\n transform: translateX(0);\n}\n\n.mobile-nav-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n.mobile-nav-header span {\n font-weight: 600;\n font-size: 16px;\n color: var(--mj-text-primary);\n}\n.mobile-nav-header .close-btn {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-muted);\n font-size: 18px;\n transition: background 0.15s;\n}\n.mobile-nav-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n}\n\n.mobile-nav-content {\n flex: 1;\n overflow-y: auto;\n padding: 16px 0;\n}\n\n.mobile-nav-section-title {\n padding: 8px 20px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-disabled);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.mobile-nav-footer {\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.mobile-nav-action {\n position: relative;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n transition: background 0.15s;\n width: 100%;\n text-align: left;\n}\n.mobile-nav-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n.mobile-nav-action i {\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n/* Mobile Responsive Styles */\n@media (max-width: 768px) {\n .hamburger-btn {\n display: flex;\n }\n\n .desktop-nav {\n display: none !important;\n }\n\n .desktop-only {\n display: none !important;\n }\n\n .mobile-nav-overlay {\n display: block;\n }\n\n .mobile-nav-drawer {\n display: flex;\n }\n\n .shell-header {\n padding: 0 12px;\n gap: 8px;\n }\n\n /* Keep the right-edge cluster (chat/nav-bar app icons + avatar) on one row.\n Without pinning this, the icons can wrap and the avatar drops onto a second\n line, stacking under the chat icon. */\n .header-actions {\n flex-direction: row;\n flex-wrap: nowrap;\n }\n .header-actions .user-menu,\n .header-actions .nav-bar-apps,\n .header-actions .search-btn {\n flex-shrink: 0;\n }\n\n /* Search bar collapses to the icon-only circle on small viewports \u2014\n the placeholder text + kbd chip are already hidden via .desktop-only.\n The omnibar-off mobile trigger (.search-btn-mobile) becomes visible here;\n its .desktop-only composite sibling is hidden by the rule above. */\n .search-btn {\n display: flex;\n width: 40px;\n height: 40px;\n padding: 0;\n justify-content: center;\n border: none;\n border-radius: 50%;\n background: none;\n }\n .search-btn i {\n font-size: var(--mj-text-lg);\n }\n .search-btn:hover {\n background: var(--mj-bg-surface-hover);\n border: none;\n }\n}\n\n/* Settings Full-Screen Window Styles */\n::ng-deep .settings-fullscreen-window {\n /* Remove window chrome for full-screen feel */\n box-shadow: none !important;\n border: none !important;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 12px 16px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-title {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-actions {\n gap: 4px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action {\n width: 32px;\n height: 32px;\n border-radius: 6px;\n}\n\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n::ng-deep .settings-fullscreen-window .k-window-content {\n padding: 0;\n overflow: auto;\n background: var(--mj-bg-page);\n}\n\n/* Hide minimize/maximize buttons - only show close */\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Minimize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action[title=\"Maximize\"],\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-minimize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window-maximize,\n::ng-deep .settings-fullscreen-window .k-window-titlebar-action .k-i-window {\n display: none !important;\n}\n\n/* Universal search is a right-anchored bar affordance in header-actions\n (2026-07 design review round 2): both experiences still open as overlays \u2014\n the bar is a trigger, not an inline input. Icon-only under 768px. */\n\n/* ========================================\n SEARCH POPUP\n ======================================== */\n\n.search-popup-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.3);\n z-index: 9999;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n.search-popup {\n position: absolute;\n top: 60px; /* Below header */\n right: 16px;\n width: 480px;\n max-width: calc(100vw - 32px);\n background: var(--mj-bg-surface-elevated);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-xl);\n z-index: 10000;\n opacity: 0;\n transform: translateY(-10px);\n pointer-events: none;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.search-popup.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n}\n\n.search-popup-content {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px;\n}\n\n.search-entity-dropdown {\n min-width: 140px;\n max-width: 180px;\n flex-shrink: 0;\n}\n\n.search-input {\n flex: 1;\n min-width: 0;\n height: 40px;\n padding: 8px 12px;\n font-size: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n outline: none;\n display: block !important;\n box-sizing: border-box;\n}\n\n.search-input:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.search-submit-btn {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n border: none;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.search-submit-btn:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.search-submit-btn:active {\n background: var(--mj-brand-primary-hover);\n}\n\n/* Mobile notification badge */\n.notification-badge-mobile {\n position: absolute;\n top: 8px;\n right: 8px;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n font-size: 11px;\n font-weight: 600;\n border-radius: 9px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n}\n\n/* Mobile-specific search popup adjustments */\n@media (max-width: 768px) {\n .search-popup {\n top: 60px;\n left: 16px;\n right: 16px;\n width: auto;\n max-width: none;\n }\n\n .search-popup-content {\n flex-wrap: wrap;\n }\n\n .search-entity-dropdown {\n width: 100%;\n }\n\n .search-input {\n flex: 1;\n min-width: 0;\n }\n}\n\n/* ========================================\n PIN PROGRESS OVERLAY\n ======================================== */\n.pin-progress-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-text-primary) 40%, transparent);\n z-index: 100000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: pinBackdropIn 0.2s ease;\n}\n\n@keyframes pinBackdropIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.pin-progress-modal {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-xl);\n padding: 28px 40px;\n display: flex;\n align-items: center;\n gap: 16px;\n box-shadow: 0 16px 48px color-mix(in srgb, var(--mj-text-primary) 30%, transparent);\n animation: pinModalIn 0.25s ease;\n}\n\n@keyframes pinModalIn {\n from { opacity: 0; transform: scale(0.9) translateY(8px); }\n to { opacity: 1; transform: scale(1) translateY(0); }\n}\n\n.pin-progress-text {\n font-size: var(--mj-text-sm);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n/* ============================================================\n Global Activity indicator (P3)\n ============================================================ */\n.activity-wrap { position: relative; display: inline-flex; }\n.activity-btn { position: relative; }\n.activity-btn .activity-pulse { color: var(--mj-brand-primary); }\n.activity-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 700;\n line-height: 16px;\n text-align: center;\n}\n.activity-drawer {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 320px;\n max-height: 420px;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-elevated);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 8px 28px color-mix(in srgb, var(--mj-text-primary) 18%, transparent);\n z-index: 1000;\n overflow: hidden;\n}\n.activity-drawer-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n font-weight: 700;\n font-size: 0.85rem;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n}\n.activity-clear {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n font-size: 0.8rem;\n padding: 4px 6px;\n border-radius: 6px;\n}\n.activity-clear:hover { color: var(--mj-text-primary); background: var(--mj-bg-surface-hover); }\n.activity-list { overflow-y: auto; padding: 6px; }\n.activity-row {\n display: flex;\n gap: 10px;\n padding: 9px 8px;\n border-radius: 8px;\n}\n.activity-row:hover { background: var(--mj-bg-surface-hover); }\n.activity-row-icon { margin-top: 2px; color: var(--mj-brand-primary); font-size: 0.85rem; }\n.activity-row.is-error .activity-row-icon { color: var(--mj-status-error); }\n.activity-row-body { flex: 1; min-width: 0; }\n.activity-row-label { font-size: 0.82rem; font-weight: 600; color: var(--mj-text-primary); }\n.activity-row-detail { font-size: 0.72rem; color: var(--mj-text-muted); margin-top: 1px; }\n.activity-bar {\n margin-top: 6px;\n height: 4px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 2px;\n overflow: hidden;\n}\n.activity-bar-fill { height: 100%; background: var(--mj-brand-primary); transition: width 0.3s ease; }\n\n"] }]
|
|
3238
3468
|
}], () => [{ type: i1.ApplicationManager }, { type: i1.WorkspaceStateManager }, { type: i1.GoldenLayoutManager }, { type: i1.TabService }, { type: i2.NavigationService }, { type: i3.ActivatedRoute }, { type: i3.Router }, { type: i4.MJAuthBase }, { type: i0.ChangeDetectorRef }, { type: i5.UserAvatarService }, { type: i6.UserSharingCenterDialogService }, { type: i7.AboutDialogService }, { type: i8.ProfileDialogService }, { type: i0.ViewContainerRef }, { type: i2.TitleService }, { type: i2.DeveloperModeService }, { type: i9.StartupValidationService }, { type: i10.CommandPaletteService }, { type: i2.ThemeService }, { type: i2.HomeAppPinService }, { type: i11.FileOpenService }, { type: i12.FeedbackDialogService }, { type: i12.FeedbackService }, { type: i2.ActivityService }], { searchInput: [{
|
|
3239
3469
|
type: ViewChild,
|
|
3240
3470
|
args: ['searchInput']
|
|
3471
|
+
}], omnibarPalette: [{
|
|
3472
|
+
type: ViewChild,
|
|
3473
|
+
args: ['omnibarPalette']
|
|
3241
3474
|
}], shellSearchComposite: [{
|
|
3242
3475
|
type: ViewChild,
|
|
3243
3476
|
args: ['shellSearchComposite']
|
|
@@ -3257,5 +3490,5 @@ export class ShellComponent extends BaseAngularComponent {
|
|
|
3257
3490
|
type: HostListener,
|
|
3258
3491
|
args: ['document:click']
|
|
3259
3492
|
}] }); })();
|
|
3260
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShellComponent, { className: "ShellComponent", filePath: "src/lib/shell/shell.component.ts", lineNumber:
|
|
3493
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ShellComponent, { className: "ShellComponent", filePath: "src/lib/shell/shell.component.ts", lineNumber: 69 }); })();
|
|
3261
3494
|
//# sourceMappingURL=shell.component.js.map
|