@memberjunction/ng-explorer-core 6.2.0-edge.0 → 6.2.0-edge.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/dist/app-routing.module.d.ts +23 -1
  2. package/dist/app-routing.module.d.ts.map +1 -1
  3. package/dist/app-routing.module.js +50 -14
  4. package/dist/app-routing.module.js.map +1 -1
  5. package/dist/generated/lazy-feature-config.d.ts +1 -1
  6. package/dist/generated/lazy-feature-config.d.ts.map +1 -1
  7. package/dist/generated/lazy-feature-config.js +12 -1
  8. package/dist/generated/lazy-feature-config.js.map +1 -1
  9. package/dist/lib/command-palette/command-palette.component.d.ts +7 -1
  10. package/dist/lib/command-palette/command-palette.component.d.ts.map +1 -1
  11. package/dist/lib/command-palette/command-palette.component.js +28 -14
  12. package/dist/lib/command-palette/command-palette.component.js.map +1 -1
  13. package/dist/lib/conversation-feedback/conversation-feedback.d.ts +103 -13
  14. package/dist/lib/conversation-feedback/conversation-feedback.d.ts.map +1 -1
  15. package/dist/lib/conversation-feedback/conversation-feedback.js +219 -67
  16. package/dist/lib/conversation-feedback/conversation-feedback.js.map +1 -1
  17. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts +64 -10
  18. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.d.ts.map +1 -1
  19. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js +172 -66
  20. package/dist/lib/dashboard-preferences-dialog/dashboard-preferences-dialog.component.js.map +1 -1
  21. package/dist/lib/generic/resource-container-component.d.ts +19 -5
  22. package/dist/lib/generic/resource-container-component.d.ts.map +1 -1
  23. package/dist/lib/generic/resource-container-component.js +43 -13
  24. package/dist/lib/generic/resource-container-component.js.map +1 -1
  25. package/dist/lib/guards/entities.guard.d.ts +4 -0
  26. package/dist/lib/guards/entities.guard.d.ts.map +1 -1
  27. package/dist/lib/guards/entities.guard.js +10 -2
  28. package/dist/lib/guards/entities.guard.js.map +1 -1
  29. package/dist/lib/identity-claims/claim-redeem.component.d.ts +4 -0
  30. package/dist/lib/identity-claims/claim-redeem.component.d.ts.map +1 -1
  31. package/dist/lib/identity-claims/claim-redeem.component.js +10 -2
  32. package/dist/lib/identity-claims/claim-redeem.component.js.map +1 -1
  33. package/dist/lib/oauth/oauth-callback.component.d.ts +4 -0
  34. package/dist/lib/oauth/oauth-callback.component.d.ts.map +1 -1
  35. package/dist/lib/oauth/oauth-callback.component.js +10 -2
  36. package/dist/lib/oauth/oauth-callback.component.js.map +1 -1
  37. package/dist/lib/profile/profile-dialog.component.d.ts.map +1 -1
  38. package/dist/lib/profile/profile-dialog.component.js +194 -191
  39. package/dist/lib/profile/profile-dialog.component.js.map +1 -1
  40. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts +20 -2
  41. package/dist/lib/resource-wrappers/artifact-resource.component.d.ts.map +1 -1
  42. package/dist/lib/resource-wrappers/artifact-resource.component.js +33 -9
  43. package/dist/lib/resource-wrappers/artifact-resource.component.js.map +1 -1
  44. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts +80 -10
  45. package/dist/lib/resource-wrappers/chat-collections-resource.component.d.ts.map +1 -1
  46. package/dist/lib/resource-wrappers/chat-collections-resource.component.js +168 -56
  47. package/dist/lib/resource-wrappers/chat-collections-resource.component.js.map +1 -1
  48. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts +199 -25
  49. package/dist/lib/resource-wrappers/chat-conversations-resource.component.d.ts.map +1 -1
  50. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js +534 -182
  51. package/dist/lib/resource-wrappers/chat-conversations-resource.component.js.map +1 -1
  52. package/dist/lib/resource-wrappers/chat-deeplink-params.d.ts +2 -0
  53. package/dist/lib/resource-wrappers/chat-deeplink-params.d.ts.map +1 -1
  54. package/dist/lib/resource-wrappers/chat-deeplink-params.js +5 -1
  55. package/dist/lib/resource-wrappers/chat-deeplink-params.js.map +1 -1
  56. package/dist/lib/resource-wrappers/chat-search-routing.d.ts +25 -0
  57. package/dist/lib/resource-wrappers/chat-search-routing.d.ts.map +1 -0
  58. package/dist/lib/resource-wrappers/chat-search-routing.js +24 -0
  59. package/dist/lib/resource-wrappers/chat-search-routing.js.map +1 -0
  60. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts +14 -2
  61. package/dist/lib/resource-wrappers/chat-tasks-resource.component.d.ts.map +1 -1
  62. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js +32 -8
  63. package/dist/lib/resource-wrappers/chat-tasks-resource.component.js.map +1 -1
  64. package/dist/lib/resource-wrappers/compose-email-fallback.d.ts +46 -0
  65. package/dist/lib/resource-wrappers/compose-email-fallback.d.ts.map +1 -0
  66. package/dist/lib/resource-wrappers/compose-email-fallback.js +62 -0
  67. package/dist/lib/resource-wrappers/compose-email-fallback.js.map +1 -0
  68. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts +54 -8
  69. package/dist/lib/resource-wrappers/dashboard-resource.component.d.ts.map +1 -1
  70. package/dist/lib/resource-wrappers/dashboard-resource.component.js +138 -46
  71. package/dist/lib/resource-wrappers/dashboard-resource.component.js.map +1 -1
  72. package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts +223 -30
  73. package/dist/lib/resource-wrappers/livekit-room-resource.component.d.ts.map +1 -1
  74. package/dist/lib/resource-wrappers/livekit-room-resource.component.js +438 -118
  75. package/dist/lib/resource-wrappers/livekit-room-resource.component.js.map +1 -1
  76. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts +7 -3
  77. package/dist/lib/resource-wrappers/search-results-resource.component.d.ts.map +1 -1
  78. package/dist/lib/resource-wrappers/search-results-resource.component.js +23 -15
  79. package/dist/lib/resource-wrappers/search-results-resource.component.js.map +1 -1
  80. package/dist/lib/resource-wrappers/view-resource.component.d.ts +74 -11
  81. package/dist/lib/resource-wrappers/view-resource.component.d.ts.map +1 -1
  82. package/dist/lib/resource-wrappers/view-resource.component.js +214 -68
  83. package/dist/lib/resource-wrappers/view-resource.component.js.map +1 -1
  84. package/dist/lib/services/server-connectivity.service.d.ts +9 -4
  85. package/dist/lib/services/server-connectivity.service.d.ts.map +1 -1
  86. package/dist/lib/services/server-connectivity.service.js +56 -12
  87. package/dist/lib/services/server-connectivity.service.js.map +1 -1
  88. package/dist/lib/services/startup-validation.service.d.ts +4 -0
  89. package/dist/lib/services/startup-validation.service.d.ts.map +1 -1
  90. package/dist/lib/services/startup-validation.service.js +10 -2
  91. package/dist/lib/services/startup-validation.service.js.map +1 -1
  92. package/dist/lib/services/system-validation.service.d.ts +13 -1
  93. package/dist/lib/services/system-validation.service.d.ts.map +1 -1
  94. package/dist/lib/services/system-validation.service.js +29 -5
  95. package/dist/lib/services/system-validation.service.js.map +1 -1
  96. package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts +54 -4
  97. package/dist/lib/shell/components/dialogs/app-access-dialog.component.d.ts.map +1 -1
  98. package/dist/lib/shell/components/dialogs/app-access-dialog.component.js +130 -40
  99. package/dist/lib/shell/components/dialogs/app-access-dialog.component.js.map +1 -1
  100. package/dist/lib/shell/components/header/app-nav.component.d.ts +29 -1
  101. package/dist/lib/shell/components/header/app-nav.component.d.ts.map +1 -1
  102. package/dist/lib/shell/components/header/app-nav.component.js +56 -12
  103. package/dist/lib/shell/components/header/app-nav.component.js.map +1 -1
  104. package/dist/lib/shell/components/header/app-switcher.component.d.ts +33 -5
  105. package/dist/lib/shell/components/header/app-switcher.component.d.ts.map +1 -1
  106. package/dist/lib/shell/components/header/app-switcher.component.js +85 -29
  107. package/dist/lib/shell/components/header/app-switcher.component.js.map +1 -1
  108. package/dist/lib/shell/components/record-open/record-origin-crumb.component.js +1 -1
  109. package/dist/lib/shell/components/record-open/record-origin-crumb.component.js.map +1 -1
  110. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts +50 -6
  111. package/dist/lib/shell/components/tabs/component-cache-manager.d.ts.map +1 -1
  112. package/dist/lib/shell/components/tabs/component-cache-manager.js +95 -22
  113. package/dist/lib/shell/components/tabs/component-cache-manager.js.map +1 -1
  114. package/dist/lib/shell/components/tabs/tab-container.component.d.ts +91 -9
  115. package/dist/lib/shell/components/tabs/tab-container.component.d.ts.map +1 -1
  116. package/dist/lib/shell/components/tabs/tab-container.component.js +257 -101
  117. package/dist/lib/shell/components/tabs/tab-container.component.js.map +1 -1
  118. package/dist/lib/shell/loading-themes.d.ts +16 -12
  119. package/dist/lib/shell/loading-themes.d.ts.map +1 -1
  120. package/dist/lib/shell/loading-themes.js +145 -137
  121. package/dist/lib/shell/loading-themes.js.map +1 -1
  122. package/dist/lib/shell/readiness-beacon.d.ts +2 -0
  123. package/dist/lib/shell/readiness-beacon.d.ts.map +1 -1
  124. package/dist/lib/shell/readiness-beacon.js +5 -1
  125. package/dist/lib/shell/readiness-beacon.js.map +1 -1
  126. package/dist/lib/shell/services/about-dialog.service.d.ts +6 -0
  127. package/dist/lib/shell/services/about-dialog.service.d.ts.map +1 -1
  128. package/dist/lib/shell/services/about-dialog.service.js +16 -4
  129. package/dist/lib/shell/services/about-dialog.service.js.map +1 -1
  130. package/dist/lib/shell/services/profile-dialog.service.d.ts +6 -0
  131. package/dist/lib/shell/services/profile-dialog.service.d.ts.map +1 -1
  132. package/dist/lib/shell/services/profile-dialog.service.js +16 -4
  133. package/dist/lib/shell/services/profile-dialog.service.js.map +1 -1
  134. package/dist/lib/shell/services/user-sharing-center-dialog.service.d.ts +6 -0
  135. package/dist/lib/shell/services/user-sharing-center-dialog.service.d.ts.map +1 -1
  136. package/dist/lib/shell/services/user-sharing-center-dialog.service.js +15 -3
  137. package/dist/lib/shell/services/user-sharing-center-dialog.service.js.map +1 -1
  138. package/dist/lib/shell/shell.component.d.ts +264 -39
  139. package/dist/lib/shell/shell.component.d.ts.map +1 -1
  140. package/dist/lib/shell/shell.component.js +697 -294
  141. package/dist/lib/shell/shell.component.js.map +1 -1
  142. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts +64 -8
  143. package/dist/lib/single-dashboard/Components/add-item/add-item.component.d.ts.map +1 -1
  144. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js +129 -37
  145. package/dist/lib/single-dashboard/Components/add-item/add-item.component.js.map +1 -1
  146. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.d.ts +26 -2
  147. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.d.ts.map +1 -1
  148. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js +48 -10
  149. package/dist/lib/single-dashboard/Components/delete-item/delete-item.component.js.map +1 -1
  150. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts +84 -6
  151. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.d.ts.map +1 -1
  152. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js +133 -29
  153. package/dist/lib/single-dashboard/Components/edit-dashboard/edit-dashboard.component.js.map +1 -1
  154. package/dist/lib/single-dashboard/single-dashboard.component.d.ts +173 -23
  155. package/dist/lib/single-dashboard/single-dashboard.component.d.ts.map +1 -1
  156. package/dist/lib/single-dashboard/single-dashboard.component.js +383 -109
  157. package/dist/lib/single-dashboard/single-dashboard.component.js.map +1 -1
  158. package/dist/lib/single-list-detail/single-list-detail.component.d.ts +383 -55
  159. package/dist/lib/single-list-detail/single-list-detail.component.d.ts.map +1 -1
  160. package/dist/lib/single-list-detail/single-list-detail.component.js +962 -326
  161. package/dist/lib/single-list-detail/single-list-detail.component.js.map +1 -1
  162. package/dist/lib/single-query/single-query.component.d.ts +22 -2
  163. package/dist/lib/single-query/single-query.component.d.ts.map +1 -1
  164. package/dist/lib/single-query/single-query.component.js +40 -10
  165. package/dist/lib/single-query/single-query.component.js.map +1 -1
  166. package/dist/lib/single-record/single-record.component.d.ts +41 -3
  167. package/dist/lib/single-record/single-record.component.d.ts.map +1 -1
  168. package/dist/lib/single-record/single-record.component.js +71 -11
  169. package/dist/lib/single-record/single-record.component.js.map +1 -1
  170. package/dist/lib/single-search-result/single-search-result.component.d.ts +23 -3
  171. package/dist/lib/single-search-result/single-search-result.component.d.ts.map +1 -1
  172. package/dist/lib/single-search-result/single-search-result.component.js +42 -12
  173. package/dist/lib/single-search-result/single-search-result.component.js.map +1 -1
  174. package/dist/lib/system-validation/system-validation-banner.component.d.ts +12 -2
  175. package/dist/lib/system-validation/system-validation-banner.component.d.ts.map +1 -1
  176. package/dist/lib/system-validation/system-validation-banner.component.js +25 -5
  177. package/dist/lib/system-validation/system-validation-banner.component.js.map +1 -1
  178. package/dist/lib/user-menu/user-menu.types.d.ts +4 -0
  179. package/dist/lib/user-menu/user-menu.types.d.ts.map +1 -1
  180. package/dist/lib/user-menu/user-menu.types.js +10 -2
  181. package/dist/lib/user-menu/user-menu.types.js.map +1 -1
  182. package/dist/lib/user-notifications/user-notifications.component.d.ts +59 -7
  183. package/dist/lib/user-notifications/user-notifications.component.d.ts.map +1 -1
  184. package/dist/lib/user-notifications/user-notifications.component.js +151 -47
  185. package/dist/lib/user-notifications/user-notifications.component.js.map +1 -1
  186. package/dist/lib/user-profile/user-profile.component.d.ts +3 -2
  187. package/dist/lib/user-profile/user-profile.component.d.ts.map +1 -1
  188. package/dist/lib/user-profile/user-profile.component.js +5 -4
  189. package/dist/lib/user-profile/user-profile.component.js.map +1 -1
  190. package/package.json +52 -52
@@ -158,20 +158,60 @@ export class TabContainerComponent extends BaseAngularComponent {
158
158
  appRef;
159
159
  environmentInjector;
160
160
  cdr;
161
- glContainer;
162
- directContentContainer;
163
- recordsGlContainer;
161
+ GlContainer;
162
+ /** @deprecated Use {@link GlContainer}. */
163
+ get glContainer() {
164
+ return this.GlContainer;
165
+ }
166
+ /** @deprecated Use {@link GlContainer}. */
167
+ set glContainer(value) {
168
+ this.GlContainer = value;
169
+ }
170
+ DirectContentContainer;
171
+ /** @deprecated Use {@link DirectContentContainer}. */
172
+ get directContentContainer() {
173
+ return this.DirectContentContainer;
174
+ }
175
+ /** @deprecated Use {@link DirectContentContainer}. */
176
+ set directContentContainer(value) {
177
+ this.DirectContentContainer = value;
178
+ }
179
+ RecordsGlContainer;
180
+ /** @deprecated Use {@link RecordsGlContainer}. */
181
+ get recordsGlContainer() {
182
+ return this.RecordsGlContainer;
183
+ }
184
+ /** @deprecated Use {@link RecordsGlContainer}. */
185
+ set recordsGlContainer(value) {
186
+ this.RecordsGlContainer = value;
187
+ }
164
188
  /**
165
189
  * Emitted when the first resource component finishes loading.
166
190
  * This allows the shell to keep showing its loading indicator until the first
167
191
  * resource is ready, eliminating the visual gap between shell loading and resource loading.
168
192
  */
169
- firstResourceLoadComplete = new EventEmitter();
193
+ FirstResourceLoadComplete = new EventEmitter();
194
+ /**
195
+ * @deprecated Use {@link FirstResourceLoadComplete}.
196
+ *
197
+ * The same emitter under the old binding name, so a template still binding
198
+ * (firstResourceLoadComplete) keeps working. Must stay AFTER FirstResourceLoadComplete: class fields
199
+ * initialise in order, and the other way round this captures undefined.
200
+ */
201
+ firstResourceLoadComplete = this.FirstResourceLoadComplete;
170
202
  /**
171
203
  * Emitted when Golden Layout fails to initialize after multiple retries.
172
204
  * The shell can use this to show an error dialog and redirect.
173
205
  */
174
- layoutInitError = new EventEmitter();
206
+ LayoutInitError = new EventEmitter();
207
+ /**
208
+ * @deprecated Use {@link LayoutInitError}.
209
+ *
210
+ * The same emitter under the old binding name, so a template still binding
211
+ * (layoutInitError) keeps working. Must stay AFTER LayoutInitError: class fields
212
+ * initialise in order, and the other way round this captures undefined.
213
+ */
214
+ layoutInitError = this.LayoutInitError;
175
215
  pinService = inject(HomeAppPinService);
176
216
  navigationService = inject(NavigationService);
177
217
  recordSwitcher = inject(RecordSwitcherService);
@@ -201,7 +241,15 @@ export class TabContainerComponent extends BaseAngularComponent {
201
241
  cacheManager;
202
242
  // Single-resource mode: render component directly without Golden Layout
203
243
  // This avoids the 20px height issue when GL header is hidden
204
- useSingleResourceMode = false;
244
+ UseSingleResourceMode = false;
245
+ /** @deprecated Use {@link UseSingleResourceMode}. */
246
+ get useSingleResourceMode() {
247
+ return this.UseSingleResourceMode;
248
+ }
249
+ /** @deprecated Use {@link UseSingleResourceMode}. */
250
+ set useSingleResourceMode(value) {
251
+ this.UseSingleResourceMode = value;
252
+ }
205
253
  singleResourceComponentRef = null;
206
254
  /** Cache identity of the current single-resource component for detachment */
207
255
  singleResourceCacheIdentity = null;
@@ -209,10 +257,42 @@ export class TabContainerComponent extends BaseAngularComponent {
209
257
  currentSingleResourceSignature = null; // Track loaded content signature to avoid unnecessary reloads
210
258
  isCreatingInitialTabs = false; // Flag to prevent syncTabsWithConfiguration during initial tab creation
211
259
  // Context menu state
212
- contextMenuVisible = false;
213
- contextMenuX = 0;
214
- contextMenuY = 0;
215
- contextMenuTabId = null;
260
+ ContextMenuVisible = false;
261
+ /** @deprecated Use {@link ContextMenuVisible}. */
262
+ get contextMenuVisible() {
263
+ return this.ContextMenuVisible;
264
+ }
265
+ /** @deprecated Use {@link ContextMenuVisible}. */
266
+ set contextMenuVisible(value) {
267
+ this.ContextMenuVisible = value;
268
+ }
269
+ ContextMenuX = 0;
270
+ /** @deprecated Use {@link ContextMenuX}. */
271
+ get contextMenuX() {
272
+ return this.ContextMenuX;
273
+ }
274
+ /** @deprecated Use {@link ContextMenuX}. */
275
+ set contextMenuX(value) {
276
+ this.ContextMenuX = value;
277
+ }
278
+ ContextMenuY = 0;
279
+ /** @deprecated Use {@link ContextMenuY}. */
280
+ get contextMenuY() {
281
+ return this.ContextMenuY;
282
+ }
283
+ /** @deprecated Use {@link ContextMenuY}. */
284
+ set contextMenuY(value) {
285
+ this.ContextMenuY = value;
286
+ }
287
+ ContextMenuTabId = null;
288
+ /** @deprecated Use {@link ContextMenuTabId}. */
289
+ get contextMenuTabId() {
290
+ return this.ContextMenuTabId;
291
+ }
292
+ /** @deprecated Use {@link ContextMenuTabId}. */
293
+ set contextMenuTabId(value) {
294
+ this.ContextMenuTabId = value;
295
+ }
216
296
  /** The control that opened the context menu — focus returns here on close */
217
297
  contextMenuAnchor = null;
218
298
  // ---- RECORDS region (records-style record opens) ----
@@ -606,7 +686,7 @@ export class TabContainerComponent extends BaseAngularComponent {
606
686
  if (this.recordsLayoutInitialized) {
607
687
  return;
608
688
  }
609
- const container = this.recordsGlContainer?.nativeElement;
689
+ const container = this.RecordsGlContainer?.nativeElement;
610
690
  if (!container) {
611
691
  return; // Template not settled yet — the next sync pass retries
612
692
  }
@@ -742,7 +822,7 @@ export class TabContainerComponent extends BaseAngularComponent {
742
822
  }), this.layoutManager.TabDoubleClicked.subscribe(tabId => {
743
823
  this.workspaceManager.TogglePin(tabId);
744
824
  }), this.layoutManager.TabRightClicked.subscribe(event => {
745
- this.showContextMenu(event.x, event.y, event.tabId, event.anchorEl);
825
+ this.ShowContextMenu(event.x, event.y, event.tabId, event.anchorEl);
746
826
  }));
747
827
  this.wireRecordsLayoutEvents();
748
828
  // Breakpoint crossings rebuild the records GL in the other chrome mode
@@ -780,7 +860,7 @@ export class TabContainerComponent extends BaseAngularComponent {
780
860
  // the region is the visible surface for this configuration.
781
861
  this.syncRecordsRegion(config);
782
862
  this.updateRecordSurfaceState(config);
783
- if (this.useSingleResourceMode) {
863
+ if (this.UseSingleResourceMode) {
784
864
  // In single-resource mode, reload content if the tab content changed
785
865
  // The same tab ID can have different content (tab gets reused)
786
866
  const activeTab = config.tabs.find(t => t.id === config.activeTabId) || config.tabs[0];
@@ -903,12 +983,12 @@ export class TabContainerComponent extends BaseAngularComponent {
903
983
  }), this.recordsLayoutManager.TabDoubleClicked.subscribe(tabId => {
904
984
  this.workspaceManager.TogglePin(tabId);
905
985
  }), this.recordsLayoutManager.TabRightClicked.subscribe(event => {
906
- this.showContextMenu(event.x, event.y, event.tabId, event.anchorEl);
986
+ this.ShowContextMenu(event.x, event.y, event.tabId, event.anchorEl);
907
987
  }));
908
988
  }
909
989
  ngAfterViewInit() {
910
990
  // Initialize Golden Layout only if we're not in single-resource mode
911
- if (!this.useSingleResourceMode) {
991
+ if (!this.UseSingleResourceMode) {
912
992
  this.initializeGoldenLayout();
913
993
  }
914
994
  else {
@@ -922,13 +1002,13 @@ export class TabContainerComponent extends BaseAngularComponent {
922
1002
  */
923
1003
  initializeGoldenLayout(forceCreateTabs = false) {
924
1004
  // If we are in single resource mode we do NOT need to do this work as golden layout should not exist in that state
925
- if (this.useSingleResourceMode)
1005
+ if (this.UseSingleResourceMode)
926
1006
  return;
927
- if (!this.glContainer?.nativeElement) {
1007
+ if (!this.GlContainer?.nativeElement) {
928
1008
  this.layoutInitRetryCount++;
929
1009
  if (this.layoutInitRetryCount > this.MAX_LAYOUT_INIT_RETRIES) {
930
1010
  console.error(`Golden Layout container not available after ${this.MAX_LAYOUT_INIT_RETRIES} retries, emitting error`);
931
- this.layoutInitError.emit();
1011
+ this.LayoutInitError.emit();
932
1012
  return;
933
1013
  }
934
1014
  console.warn(`Golden Layout container not available, retry ${this.layoutInitRetryCount}/${this.MAX_LAYOUT_INIT_RETRIES}...`);
@@ -962,7 +1042,7 @@ export class TabContainerComponent extends BaseAngularComponent {
962
1042
  return;
963
1043
  }
964
1044
  // Initialize Golden Layout (we have config now)
965
- this.layoutManager.Initialize(this.glContainer.nativeElement);
1045
+ this.layoutManager.Initialize(this.GlContainer.nativeElement);
966
1046
  // Mark layout as initialized
967
1047
  this.layoutInitialized = true;
968
1048
  // The MAIN layout hosts only non-record tabs — record tabs live in the
@@ -1062,7 +1142,7 @@ export class TabContainerComponent extends BaseAngularComponent {
1062
1142
  async ReloadAllTabs() {
1063
1143
  // Destroy all cached component instances
1064
1144
  this.cacheManager.clearCache();
1065
- if (this.useSingleResourceMode) {
1145
+ if (this.UseSingleResourceMode) {
1066
1146
  // Force reload by clearing the signature check
1067
1147
  this.currentSingleResourceSignature = null;
1068
1148
  this.singleResourceComponentRef = null;
@@ -1155,7 +1235,7 @@ export class TabContainerComponent extends BaseAngularComponent {
1155
1235
  * ensures the layout is properly sized after browser window changes.
1156
1236
  */
1157
1237
  onWindowResize() {
1158
- if (this.layoutInitialized && !this.useSingleResourceMode) {
1238
+ if (this.layoutInitialized && !this.UseSingleResourceMode) {
1159
1239
  this.layoutManager.updateSize();
1160
1240
  }
1161
1241
  }
@@ -1170,12 +1250,12 @@ export class TabContainerComponent extends BaseAngularComponent {
1170
1250
  this.previousTabBarVisible = tabBarVisible;
1171
1251
  // Determine if we should use single-resource mode
1172
1252
  const shouldUseSingleResourceMode = !tabBarVisible;
1173
- if (shouldUseSingleResourceMode !== this.useSingleResourceMode) {
1174
- this.useSingleResourceMode = shouldUseSingleResourceMode;
1253
+ if (shouldUseSingleResourceMode !== this.UseSingleResourceMode) {
1254
+ this.UseSingleResourceMode = shouldUseSingleResourceMode;
1175
1255
  // Defer detectChanges to next microtask to avoid ExpressionChangedAfterItHasBeenCheckedError
1176
1256
  // when this handler fires during an already-running change detection cycle.
1177
1257
  Promise.resolve().then(() => this.cdr.detectChanges());
1178
- if (this.useSingleResourceMode) {
1258
+ if (this.UseSingleResourceMode) {
1179
1259
  // Transitioning to single-resource mode
1180
1260
  // **CRITICAL FIX**: Wait for the template to render directContentContainer
1181
1261
  // before trying to load content. detectChanges() only marks dirty, doesn't render immediately.
@@ -1277,7 +1357,7 @@ export class TabContainerComponent extends BaseAngularComponent {
1277
1357
  }
1278
1358
  this.currentSingleResourceSignature = newSignature;
1279
1359
  // Get the container element
1280
- const container = this.directContentContainer?.nativeElement;
1360
+ const container = this.DirectContentContainer?.nativeElement;
1281
1361
  if (!container) {
1282
1362
  // Retry after view is updated
1283
1363
  setTimeout(() => this.loadSingleResourceContent(), 50);
@@ -1475,7 +1555,7 @@ export class TabContainerComponent extends BaseAngularComponent {
1475
1555
  // Remove children from the container. This detaches the wrapper DOM element
1476
1556
  // without destroying the Angular component — it lives on in the cache.
1477
1557
  // Using removeChild (not innerHTML='') to avoid aggressive DOM cleanup.
1478
- const container = this.directContentContainer?.nativeElement;
1558
+ const container = this.DirectContentContainer?.nativeElement;
1479
1559
  if (container) {
1480
1560
  while (container.firstChild) {
1481
1561
  container.removeChild(container.firstChild);
@@ -1529,7 +1609,7 @@ export class TabContainerComponent extends BaseAngularComponent {
1529
1609
  // Pre-compute and stamp the new signature so the configuration-subscription path
1530
1610
  // in single-resource mode doesn't see a "content changed" delta and trigger a
1531
1611
  // needless reload cycle (which would destroy the currently attached component).
1532
- if (this.useSingleResourceMode && this.currentSingleResourceSignature !== null) {
1612
+ if (this.UseSingleResourceMode && this.currentSingleResourceSignature !== null) {
1533
1613
  const updatedTab = {
1534
1614
  ...tab,
1535
1615
  resourceRecordId: newRecordId,
@@ -1612,7 +1692,7 @@ export class TabContainerComponent extends BaseAngularComponent {
1612
1692
  this.singleResourceCacheIdentity = null;
1613
1693
  // Clear the host container's DOM so the user isn't briefly looking at the
1614
1694
  // destroyed component's wrapper between CloseTab and the default-tab load.
1615
- const directContainer = this.directContentContainer?.nativeElement;
1695
+ const directContainer = this.DirectContentContainer?.nativeElement;
1616
1696
  if (directContainer) {
1617
1697
  while (directContainer.firstChild)
1618
1698
  directContainer.removeChild(directContainer.firstChild);
@@ -2028,11 +2108,19 @@ export class TabContainerComponent extends BaseAngularComponent {
2028
2108
  */
2029
2109
  static findResourceTypeTolerant(rows, resourceType) {
2030
2110
  const wanted = resourceType.trim().toLowerCase();
2031
- const normalize = (name) => name.trim().toLowerCase().replace(/^mj:\s*/, '');
2032
2111
  return rows.find(r => r.Name.trim().toLowerCase() === wanted)
2033
- ?? rows.find(r => normalize(r.Name) === normalize(wanted))
2112
+ ?? rows.find(r => TabContainerComponent.IsSameResourceType(r.Name, resourceType))
2034
2113
  ?? null;
2035
2114
  }
2115
+ /**
2116
+ * Whether two resource type names refer to the same type, ignoring case and the 'MJ: '
2117
+ * prefix. A loaded component's ResourceType is the stored row name ('User Views'), while
2118
+ * its tab's configuration keeps whatever the caller passed ('MJ: User Views').
2119
+ */
2120
+ static IsSameResourceType(a, b) {
2121
+ const normalize = (name) => (name ?? '').trim().toLowerCase().replace(/^mj:\s*/, '');
2122
+ return normalize(a) === normalize(b);
2123
+ }
2036
2124
  async getResourceTypeId(resourceType) {
2037
2125
  const rt = await this.getResourceTypeEntity(resourceType);
2038
2126
  if (rt) {
@@ -2236,9 +2324,17 @@ export class TabContainerComponent extends BaseAngularComponent {
2236
2324
  // because for nav items, the recordId is stored in configuration, not resourceRecordId
2237
2325
  const existingRecordId = existingResourceData?.ResourceRecordID || '';
2238
2326
  const newRecordId = tab.resourceRecordId || tab.configuration['recordId'] || '';
2239
- const needsReload = existingResourceData?.ResourceType !== tab.configuration['resourceType'] ||
2327
+ // Entity tells dynamic views apart: every one carries recordId 'dynamic', so without it
2328
+ // opening #Contacts into a tab showing #Accounts retitles the tab and keeps the Accounts
2329
+ // grid. Saved-view configs never carry Entity, so both sides are undefined there. It is
2330
+ // also part of ComponentCacheManager's key for 'dynamic', which is what stops this
2331
+ // reload from being handed back the component it just detached.
2332
+ const existingEntity = existingResourceData?.Configuration?.Entity;
2333
+ const newEntity = tab.configuration['Entity'];
2334
+ const needsReload = !TabContainerComponent.IsSameResourceType(existingResourceData?.ResourceType, tab.configuration['resourceType']) ||
2240
2335
  existingResourceData?.Configuration?.applicationId !== tab.applicationId ||
2241
2336
  existingRecordId !== newRecordId ||
2337
+ existingEntity !== newEntity ||
2242
2338
  (tab.configuration['resourceType'] === 'Custom' && existingDriverClass !== newDriverClass);
2243
2339
  if (needsReload) {
2244
2340
  // Clean up old component
@@ -2286,11 +2382,11 @@ export class TabContainerComponent extends BaseAngularComponent {
2286
2382
  /**
2287
2383
  * Show context menu
2288
2384
  */
2289
- showContextMenu(x, y, tabId, anchorEl) {
2290
- this.contextMenuX = x;
2291
- this.contextMenuY = y;
2292
- this.contextMenuTabId = tabId;
2293
- this.contextMenuVisible = true;
2385
+ ShowContextMenu(x, y, tabId, anchorEl) {
2386
+ this.ContextMenuX = x;
2387
+ this.ContextMenuY = y;
2388
+ this.ContextMenuTabId = tabId;
2389
+ this.ContextMenuVisible = true;
2294
2390
  // Remember the invoking control so closing can hand focus back (the
2295
2391
  // slot button passes itself; right-click falls back to whatever was
2296
2392
  // focused). aria-expanded reflects the open menu on the anchor.
@@ -2317,14 +2413,14 @@ export class TabContainerComponent extends BaseAngularComponent {
2317
2413
  const clickHandler = (event) => {
2318
2414
  const target = event.target;
2319
2415
  if (!target.closest('.context-menu')) {
2320
- this.hideContextMenu();
2416
+ this.HideContextMenu();
2321
2417
  document.removeEventListener('click', clickHandler, true);
2322
2418
  document.removeEventListener('keydown', keyHandler, true);
2323
2419
  }
2324
2420
  };
2325
2421
  const keyHandler = (event) => {
2326
2422
  if (event.key === 'Escape') {
2327
- this.hideContextMenu();
2423
+ this.HideContextMenu();
2328
2424
  document.removeEventListener('click', clickHandler, true);
2329
2425
  document.removeEventListener('keydown', keyHandler, true);
2330
2426
  }
@@ -2333,12 +2429,16 @@ export class TabContainerComponent extends BaseAngularComponent {
2333
2429
  document.addEventListener('keydown', keyHandler, true);
2334
2430
  }, 0);
2335
2431
  }
2432
+ /** @deprecated Use {@link ShowContextMenu}. */
2433
+ showContextMenu(x, y, tabId, anchorEl) {
2434
+ return this.ShowContextMenu(x, y, tabId, anchorEl);
2435
+ }
2336
2436
  /**
2337
2437
  * Hide context menu
2338
2438
  */
2339
- hideContextMenu(restoreFocus = true) {
2340
- this.contextMenuVisible = false;
2341
- this.contextMenuTabId = null;
2439
+ HideContextMenu(restoreFocus = true) {
2440
+ this.ContextMenuVisible = false;
2441
+ this.ContextMenuTabId = null;
2342
2442
  const anchor = this.contextMenuAnchor;
2343
2443
  this.contextMenuAnchor = null;
2344
2444
  if (anchor?.classList.contains('mj-tab-type-slot')) {
@@ -2354,12 +2454,16 @@ export class TabContainerComponent extends BaseAngularComponent {
2354
2454
  requestAnimationFrame(() => anchor.focus());
2355
2455
  }
2356
2456
  }
2457
+ /** @deprecated Use {@link HideContextMenu}. */
2458
+ hideContextMenu(restoreFocus = true) {
2459
+ return this.HideContextMenu(restoreFocus);
2460
+ }
2357
2461
  /**
2358
2462
  * role="menu" keyboard model: ArrowUp/Down rove (wrapping) over enabled
2359
2463
  * items, Home/End jump, Escape closes with focus return, Tab dismisses
2360
2464
  * (native menus don't trap Tab).
2361
2465
  */
2362
- onMenuKeydown(event) {
2466
+ OnMenuKeydown(event) {
2363
2467
  const items = Array.from(document.querySelectorAll('.context-menu [role="menuitem"]:not([disabled])'));
2364
2468
  if (items.length === 0) {
2365
2469
  return;
@@ -2387,37 +2491,53 @@ export class TabContainerComponent extends BaseAngularComponent {
2387
2491
  // deferred document-level teardown listener attaches.
2388
2492
  event.preventDefault();
2389
2493
  event.stopPropagation();
2390
- this.hideContextMenu();
2494
+ this.HideContextMenu();
2391
2495
  break;
2392
2496
  case 'Tab':
2393
- this.hideContextMenu(false);
2497
+ this.HideContextMenu(false);
2394
2498
  break;
2395
2499
  }
2396
2500
  }
2501
+ /** @deprecated Use {@link OnMenuKeydown}. */
2502
+ onMenuKeydown(event) {
2503
+ return this.OnMenuKeydown(event);
2504
+ }
2397
2505
  /**
2398
2506
  * Check if context menu tab is pinned
2399
2507
  */
2400
- get isContextTabPinned() {
2401
- if (!this.contextMenuTabId)
2508
+ get IsContextTabPinned() {
2509
+ if (!this.ContextMenuTabId)
2402
2510
  return false;
2403
- const tab = this.workspaceManager.GetTab(this.contextMenuTabId);
2511
+ const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
2404
2512
  return tab?.isPinned || false;
2405
2513
  }
2514
+ /** @deprecated Use {@link IsContextTabPinned}. */
2515
+ get isContextTabPinned() {
2516
+ return this.IsContextTabPinned;
2517
+ }
2406
2518
  /** Context tab is a records-REGION record — eligible for "Move to Workspace" */
2407
- get canContextMoveToWorkspace() {
2519
+ get CanContextMoveToWorkspace() {
2408
2520
  // Docked/region composition is a DESKTOP concept — no move actions on mobile
2409
- if (!this.contextMenuTabId || !this.RecordsStyleActive || this.mobileRecordsActive)
2521
+ if (!this.ContextMenuTabId || !this.RecordsStyleActive || this.mobileRecordsActive)
2410
2522
  return false;
2411
- const tab = this.workspaceManager.GetTab(this.contextMenuTabId);
2523
+ const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
2412
2524
  return !!tab && IsRecordsRegionTab(tab.configuration);
2413
2525
  }
2526
+ /** @deprecated Use {@link CanContextMoveToWorkspace}. */
2527
+ get canContextMoveToWorkspace() {
2528
+ return this.CanContextMoveToWorkspace;
2529
+ }
2414
2530
  /** Context tab is a DOCKED record — eligible for "Move to Records" */
2415
- get canContextMoveToRecords() {
2416
- if (!this.contextMenuTabId || !this.RecordsStyleActive || this.mobileRecordsActive)
2531
+ get CanContextMoveToRecords() {
2532
+ if (!this.ContextMenuTabId || !this.RecordsStyleActive || this.mobileRecordsActive)
2417
2533
  return false;
2418
- const tab = this.workspaceManager.GetTab(this.contextMenuTabId);
2534
+ const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
2419
2535
  return !!tab && IsRecordsTabConfiguration(tab.configuration) && IsRecordDockedToWorkspace(tab.configuration);
2420
2536
  }
2537
+ /** @deprecated Use {@link CanContextMoveToRecords}. */
2538
+ get canContextMoveToRecords() {
2539
+ return this.CanContextMoveToRecords;
2540
+ }
2421
2541
  /**
2422
2542
  * Promote: records region → main workspace layout ("Move to Workspace").
2423
2543
  * ORDER MATTERS: activate FIRST, then flip the flag. With the tab already
@@ -2426,15 +2546,19 @@ export class TabContainerComponent extends BaseAngularComponent {
2426
2546
  * (b) a single-resource→multi-tab transition triggered by the flip exempts
2427
2547
  * it from the force-pin sweep (it IS the activeTabId).
2428
2548
  */
2429
- onContextMoveToWorkspace() {
2430
- const tabId = this.contextMenuTabId;
2431
- this.hideContextMenu(false);
2549
+ OnContextMoveToWorkspace() {
2550
+ const tabId = this.ContextMenuTabId;
2551
+ this.HideContextMenu(false);
2432
2552
  if (!tabId)
2433
2553
  return;
2434
2554
  this.workspaceManager.SetActiveTab(tabId);
2435
2555
  this.workspaceManager.UpdateTabConfiguration(tabId, { [RECORD_DOCKED_TO_WORKSPACE_KEY]: true });
2436
2556
  this.assertMovedTabActivation(tabId);
2437
2557
  }
2558
+ /** @deprecated Use {@link OnContextMoveToWorkspace}. */
2559
+ onContextMoveToWorkspace() {
2560
+ return this.OnContextMoveToWorkspace();
2561
+ }
2438
2562
  /**
2439
2563
  * Demote: main workspace layout → records region ("Move to Records").
2440
2564
  * Same activate-first ordering: the flip's emission then computes
@@ -2442,15 +2566,19 @@ export class TabContainerComponent extends BaseAngularComponent {
2442
2566
  * the returned tab. `false` (not undefined) so the choice is explicit in
2443
2567
  * the persisted configuration.
2444
2568
  */
2445
- onContextMoveToRecords() {
2446
- const tabId = this.contextMenuTabId;
2447
- this.hideContextMenu(false);
2569
+ OnContextMoveToRecords() {
2570
+ const tabId = this.ContextMenuTabId;
2571
+ this.HideContextMenu(false);
2448
2572
  if (!tabId)
2449
2573
  return;
2450
2574
  this.workspaceManager.SetActiveTab(tabId);
2451
2575
  this.workspaceManager.UpdateTabConfiguration(tabId, { [RECORD_DOCKED_TO_WORKSPACE_KEY]: false });
2452
2576
  this.assertMovedTabActivation(tabId);
2453
2577
  }
2578
+ /** @deprecated Use {@link OnContextMoveToRecords}. */
2579
+ onContextMoveToRecords() {
2580
+ return this.OnContextMoveToRecords();
2581
+ }
2454
2582
  /**
2455
2583
  * A move's SOURCE layout auto-activates its next tab when the moved tab is
2456
2584
  * removed, and that GL activation WRITES BACK into the workspace — stomping
@@ -2469,69 +2597,89 @@ export class TabContainerComponent extends BaseAngularComponent {
2469
2597
  /**
2470
2598
  * Toggle pin from context menu
2471
2599
  */
2472
- onContextPin() {
2473
- if (this.contextMenuTabId) {
2474
- this.workspaceManager.TogglePin(this.contextMenuTabId);
2600
+ OnContextPin() {
2601
+ if (this.ContextMenuTabId) {
2602
+ this.workspaceManager.TogglePin(this.ContextMenuTabId);
2475
2603
  }
2476
- this.hideContextMenu();
2604
+ this.HideContextMenu();
2605
+ }
2606
+ /** @deprecated Use {@link OnContextPin}. */
2607
+ onContextPin() {
2608
+ return this.OnContextPin();
2477
2609
  }
2478
2610
  /**
2479
2611
  * Close tab from context menu
2480
2612
  */
2481
- onContextClose() {
2482
- if (this.contextMenuTabId) {
2483
- const tab = this.workspaceManager.GetTab(this.contextMenuTabId);
2613
+ OnContextClose() {
2614
+ if (this.ContextMenuTabId) {
2615
+ const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
2484
2616
  const manager = tab && this.isRecordTab(tab) ? this.recordsLayoutManager : this.layoutManager;
2485
- manager.RemoveTab(this.contextMenuTabId);
2617
+ manager.RemoveTab(this.ContextMenuTabId);
2486
2618
  }
2487
2619
  // The anchor lives on the closed tab — nothing to return focus to.
2488
- this.hideContextMenu(false);
2620
+ this.HideContextMenu(false);
2621
+ }
2622
+ /** @deprecated Use {@link OnContextClose}. */
2623
+ onContextClose() {
2624
+ return this.OnContextClose();
2489
2625
  }
2490
2626
  /**
2491
2627
  * Close all other tabs from context menu
2492
2628
  */
2493
- onContextCloseOthers() {
2494
- if (this.contextMenuTabId) {
2495
- this.workspaceManager.CloseOtherTabs(this.contextMenuTabId);
2629
+ OnContextCloseOthers() {
2630
+ if (this.ContextMenuTabId) {
2631
+ this.workspaceManager.CloseOtherTabs(this.ContextMenuTabId);
2496
2632
  }
2497
- this.hideContextMenu();
2633
+ this.HideContextMenu();
2634
+ }
2635
+ /** @deprecated Use {@link OnContextCloseOthers}. */
2636
+ onContextCloseOthers() {
2637
+ return this.OnContextCloseOthers();
2498
2638
  }
2499
2639
  /**
2500
2640
  * Close tabs to the right from context menu
2501
2641
  */
2502
- onContextCloseToRight() {
2503
- if (this.contextMenuTabId) {
2504
- this.workspaceManager.CloseTabsToRight(this.contextMenuTabId);
2642
+ OnContextCloseToRight() {
2643
+ if (this.ContextMenuTabId) {
2644
+ this.workspaceManager.CloseTabsToRight(this.ContextMenuTabId);
2505
2645
  }
2506
- this.hideContextMenu();
2646
+ this.HideContextMenu();
2647
+ }
2648
+ /** @deprecated Use {@link OnContextCloseToRight}. */
2649
+ onContextCloseToRight() {
2650
+ return this.OnContextCloseToRight();
2507
2651
  }
2508
2652
  /**
2509
2653
  * Check if context menu tab is pinned to Home dashboard
2510
2654
  */
2511
- get isContextTabPinnedToHome() {
2512
- if (!this.contextMenuTabId)
2655
+ get IsContextTabPinnedToHome() {
2656
+ if (!this.ContextMenuTabId)
2513
2657
  return false;
2514
- const tab = this.workspaceManager.GetTab(this.contextMenuTabId);
2658
+ const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
2515
2659
  if (!tab)
2516
2660
  return false;
2517
2661
  const resourceType = this.resolveResourceType(tab);
2518
2662
  return this.pinService.IsPinned(resourceType, tab.configuration);
2519
2663
  }
2664
+ /** @deprecated Use {@link IsContextTabPinnedToHome}. */
2665
+ get isContextTabPinnedToHome() {
2666
+ return this.IsContextTabPinnedToHome;
2667
+ }
2520
2668
  /**
2521
2669
  * Pin current context menu tab to Home dashboard
2522
2670
  */
2523
- async onContextPinToHome() {
2524
- if (this.isContextTabPinnedToHome) {
2525
- this.hideContextMenu();
2671
+ async OnContextPinToHome() {
2672
+ if (this.IsContextTabPinnedToHome) {
2673
+ this.HideContextMenu();
2526
2674
  return;
2527
2675
  }
2528
- if (!this.contextMenuTabId) {
2529
- this.hideContextMenu();
2676
+ if (!this.ContextMenuTabId) {
2677
+ this.HideContextMenu();
2530
2678
  return;
2531
2679
  }
2532
- const tab = this.workspaceManager.GetTab(this.contextMenuTabId);
2680
+ const tab = this.workspaceManager.GetTab(this.ContextMenuTabId);
2533
2681
  if (!tab) {
2534
- this.hideContextMenu();
2682
+ this.HideContextMenu();
2535
2683
  return;
2536
2684
  }
2537
2685
  const resourceType = this.resolveResourceType(tab);
@@ -2562,7 +2710,11 @@ export class TabContainerComponent extends BaseAngularComponent {
2562
2710
  else {
2563
2711
  MJNotificationService.Instance.CreateSimpleNotification(`"${tab.title}" is already pinned to Home`, 'info', 3000);
2564
2712
  }
2565
- this.hideContextMenu();
2713
+ this.HideContextMenu();
2714
+ }
2715
+ /** @deprecated Use {@link OnContextPinToHome}. */
2716
+ async onContextPinToHome() {
2717
+ return this.OnContextPinToHome();
2566
2718
  }
2567
2719
  /**
2568
2720
  * Resolve a WorkspaceTab's resource type string for pin matching
@@ -2589,12 +2741,12 @@ export class TabContainerComponent extends BaseAngularComponent {
2589
2741
  try {
2590
2742
  // Find the active content element — differs by mode
2591
2743
  let contentEl = null;
2592
- if (this.useSingleResourceMode) {
2593
- contentEl = this.directContentContainer?.nativeElement ?? null;
2744
+ if (this.UseSingleResourceMode) {
2745
+ contentEl = this.DirectContentContainer?.nativeElement ?? null;
2594
2746
  }
2595
2747
  else {
2596
2748
  // In Golden Layout mode, find the active tab's content pane
2597
- contentEl = this.glContainer?.nativeElement?.querySelector('.lm_item_container .lm_content');
2749
+ contentEl = this.GlContainer?.nativeElement?.querySelector('.lm_item_container .lm_content');
2598
2750
  }
2599
2751
  if (!contentEl)
2600
2752
  return;
@@ -2618,11 +2770,11 @@ export class TabContainerComponent extends BaseAngularComponent {
2618
2770
  async CaptureActiveThumbnail() {
2619
2771
  try {
2620
2772
  let contentEl = null;
2621
- if (this.useSingleResourceMode) {
2622
- contentEl = this.directContentContainer?.nativeElement ?? null;
2773
+ if (this.UseSingleResourceMode) {
2774
+ contentEl = this.DirectContentContainer?.nativeElement ?? null;
2623
2775
  }
2624
2776
  else {
2625
- contentEl = this.glContainer?.nativeElement?.querySelector('.lm_item_container .lm_content');
2777
+ contentEl = this.GlContainer?.nativeElement?.querySelector('.lm_item_container .lm_content');
2626
2778
  }
2627
2779
  if (!contentEl)
2628
2780
  return undefined;
@@ -2638,7 +2790,7 @@ export class TabContainerComponent extends BaseAngularComponent {
2638
2790
  * forever we emit all events upstream
2639
2791
  */
2640
2792
  emitFirstLoadCompleteOnce() {
2641
- this.firstResourceLoadComplete.emit(); // do this each time to be sure we don't suppress messages
2793
+ this.FirstResourceLoadComplete.emit(); // do this each time to be sure we don't suppress messages
2642
2794
  }
2643
2795
  /**
2644
2796
  * Render an inline "missing resource component" error into a host element when
@@ -2699,12 +2851,12 @@ export class TabContainerComponent extends BaseAngularComponent {
2699
2851
  i0.ɵɵviewQuery(_c0, 5)(_c1, 5)(_c2, 5);
2700
2852
  } if (rf & 2) {
2701
2853
  let _t;
2702
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.glContainer = _t.first);
2703
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.directContentContainer = _t.first);
2704
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.recordsGlContainer = _t.first);
2854
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.GlContainer = _t.first);
2855
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.DirectContentContainer = _t.first);
2856
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.RecordsGlContainer = _t.first);
2705
2857
  } }, hostBindings: function TabContainerComponent_HostBindings(rf, ctx) { if (rf & 1) {
2706
2858
  i0.ɵɵlistener("resize", function TabContainerComponent_resize_HostBindingHandler() { return ctx.onWindowResize(); }, i0.ɵɵresolveWindow);
2707
- } }, outputs: { firstResourceLoadComplete: "firstResourceLoadComplete", layoutInitError: "layoutInitError" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 5, consts: [["directContentContainer", ""], ["glContainer", ""], ["recordsGlContainer", ""], [1, "tab-container"], [1, "main-region"], [1, "direct-content-container"], [1, "gl-container"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "left", "top"], [1, "records-region"], [3, "Title", "Icon", "Color", "Count"], [1, "records-gl-container"], [3, "VisibleChange", "ActivateRequested", "CloseRequested", "Entries", "Visible"], [3, "SwitcherRequested", "Title", "Icon", "Color", "Count"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "keydown"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-thumbtack"], [1, "context-menu-divider"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-house-chimney"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], ["aria-hidden", "true", 1, "fa-solid", "fa-angles-right"], [1, "check"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], ["type", "button", "role", "menuitem", 1, "context-menu-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-lines"]], template: function TabContainerComponent_Template(rf, ctx) { if (rf & 1) {
2859
+ } }, outputs: { FirstResourceLoadComplete: "FirstResourceLoadComplete", firstResourceLoadComplete: "firstResourceLoadComplete", LayoutInitError: "LayoutInitError", layoutInitError: "layoutInitError" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 6, vars: 5, consts: [["directContentContainer", ""], ["glContainer", ""], ["recordsGlContainer", ""], [1, "tab-container"], [1, "main-region"], [1, "direct-content-container"], [1, "gl-container"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "left", "top"], [1, "records-region"], [3, "Title", "Icon", "Color", "Count"], [1, "records-gl-container"], [3, "VisibleChange", "ActivateRequested", "CloseRequested", "Entries", "Visible"], [3, "SwitcherRequested", "Title", "Icon", "Color", "Count"], ["role", "menu", "aria-label", "Tab actions", 1, "context-menu", 3, "keydown"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-thumbtack"], [1, "context-menu-divider"], ["type", "button", "role", "menuitem", 1, "context-menu-item", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-house-chimney"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"], ["aria-hidden", "true", 1, "fa-solid", "fa-layer-group"], ["aria-hidden", "true", 1, "fa-solid", "fa-angles-right"], [1, "check"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], ["type", "button", "role", "menuitem", 1, "context-menu-item"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up-right-from-square"], ["aria-hidden", "true", 1, "fa-solid", "fa-file-lines"]], template: function TabContainerComponent_Template(rf, ctx) { if (rf & 1) {
2708
2860
  i0.ɵɵelementStart(0, "div", 3)(1, "div", 4);
2709
2861
  i0.ɵɵconditionalCreate(2, TabContainerComponent_Conditional_2_Template, 2, 0, "div", 5)(3, TabContainerComponent_Conditional_3_Template, 2, 0, "div", 6);
2710
2862
  i0.ɵɵelementEnd();
@@ -2725,17 +2877,21 @@ export class TabContainerComponent extends BaseAngularComponent {
2725
2877
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TabContainerComponent, [{
2726
2878
  type: Component,
2727
2879
  args: [{ standalone: false, selector: 'mj-tab-container', encapsulation: ViewEncapsulation.None, template: "<div class=\"tab-container\">\n\n <!-- Main region: nav pages (single-resource or main Golden Layout).\n Hidden (not destroyed) while the RECORDS region is showing, so nav\n content keeps its state and reappears instantly. -->\n <div class=\"main-region\" [class.region-hidden]=\"ShowRecordsRegion\">\n <!-- Single-Resource Mode: Direct component rendering without Golden Layout -->\n <!-- This avoids the 20px height issue when GL header is hidden -->\n @if (useSingleResourceMode) {\n <div #directContentContainer class=\"direct-content-container\"></div>\n } @else {\n <!-- Multi-Tab Mode: Golden Layout Container -->\n <div #glContainer class=\"gl-container\"></div>\n }\n </div>\n\n <!-- RECORDS region: a SEPARATE Golden Layout hosting only record tabs\n (records-style record opens). Always in the DOM once created so the\n layout survives visibility flips; shown only while the active tab is\n a record. Native GL tab bar = record tabs, drag-to-split included. -->\n @if (RecordsStyleActive) {\n <!-- Origin crumbs are PANE-LEVEL now (first element inside each record\n pane \u2014 see RecordOriginCrumbComponent); the region needs no bar. -->\n <div class=\"records-region\" [class.region-hidden]=\"!ShowRecordsRegion\">\n <!-- MOBILE: the GL tab strip is unusable at phone widths (one tab\n fits, no overflow UI) \u2014 the record bar replaces it and opens the\n record switcher sheet. The GL itself runs headerless (HideHeaders). -->\n @if (IsMobileRecords) {\n <mj-record-bar\n [Title]=\"RecordBarTitle\"\n [Icon]=\"RecordBarIcon\"\n [Color]=\"RecordBarColor\"\n [Count]=\"OpenRecordCount\"\n (SwitcherRequested)=\"OpenRecordSwitcher()\">\n </mj-record-bar>\n }\n <div #recordsGlContainer class=\"records-gl-container\"></div>\n </div>\n\n <!-- MOBILE record switcher: bottom sheet listing ALL open records\n (region + docked). Fixed-position \u2014 DOM location here is\n visual-neutral; living in tab-container keeps close routing on the\n same path as the tab context menu. -->\n <mj-record-switcher-sheet\n [Entries]=\"SwitcherEntries\"\n [Visible]=\"RecordSwitcherVisible\"\n (VisibleChange)=\"OnSwitcherVisibleChange($event)\"\n (ActivateRequested)=\"OnSwitcherActivate($event)\"\n (CloseRequested)=\"OnSwitcherClose($event)\">\n </mj-record-switcher-sheet>\n }\n\n <!-- Context Menu (only relevant in multi-tab mode). Real buttons with\n menu semantics: arrow keys rove, Escape closes with focus return to\n the invoking control (see onMenuKeydown / hideContextMenu). -->\n @if (contextMenuVisible) {\n <div\n class=\"context-menu\"\n role=\"menu\"\n aria-label=\"Tab actions\"\n (keydown)=\"onMenuKeydown($event)\"\n [style.left.px]=\"contextMenuX\"\n [style.top.px]=\"contextMenuY\">\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextPin()\">\n <i class=\"fa-solid fa-thumbtack\" aria-hidden=\"true\"></i>\n <span>{{ isContextTabPinned ? 'Unpin Tab' : 'Pin Tab' }}</span>\n </button>\n <div class=\"context-menu-divider\"></div>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" [class.new-item]=\"!isContextTabPinnedToHome\" [class.disabled]=\"isContextTabPinnedToHome\" [disabled]=\"isContextTabPinnedToHome\" (click)=\"onContextPinToHome()\">\n <i class=\"fa-solid fa-house-chimney\" aria-hidden=\"true\"></i>\n @if (isContextTabPinnedToHome) {\n <span>Pinned to Home</span>\n <span class=\"check\"><i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i></span>\n } @else {\n <span>Pin to Home</span>\n }\n </button>\n @if (canContextMoveToWorkspace || canContextMoveToRecords) {\n <div class=\"context-menu-divider\"></div>\n @if (canContextMoveToWorkspace) {\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextMoveToWorkspace()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\" aria-hidden=\"true\"></i>\n <span>Move to Workspace</span>\n </button>\n }\n @if (canContextMoveToRecords) {\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextMoveToRecords()\">\n <i class=\"fa-solid fa-file-lines\" aria-hidden=\"true\"></i>\n <span>Move to Records</span>\n </button>\n }\n }\n <div class=\"context-menu-divider\"></div>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextClose()\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n <span>Close Tab</span>\n </button>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextCloseOthers()\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i>\n <span>Close Others</span>\n </button>\n <button type=\"button\" role=\"menuitem\" class=\"context-menu-item\" (click)=\"onContextCloseToRight()\">\n <i class=\"fa-solid fa-angles-right\" aria-hidden=\"true\"></i>\n <span>Close to Right</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host {\n display: flex;\n flex: 1;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n.tab-container {\n display: flex;\n flex-direction: column;\n flex: 1;\n width: 100%;\n overflow: hidden;\n}\n\n.gl-container {\n flex: 1;\n width: 100%;\n height: 100%;\n position: relative;\n background: var(--mj-bg-page);\n}\n\n/* Main region (nav pages) and the separate RECORDS region \u2014 exactly one is\n visible at a time. CRITICAL: the hidden region keeps its FULL LAYOUT BOX\n (visibility, not display:none). Golden Layout instances live in both;\n display:none would feed GL 0-size resizes and let it initialize/restore\n against a zero baseline \u2014 the root cause of clipped tab headers, stale\n strips, and the collapsed-sliver layout. */\n.tab-container {\n position: relative;\n}\n\n.main-region,\n.records-region {\n position: absolute;\n inset: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n}\n\n/* The records GL host fills the region below the origin bar. Must keep a\n real layout box at all times (see the region comment above) \u2014 it's a flex\n child of an always-sized absolute region, so it does. */\n.records-gl-container {\n flex: 1;\n min-height: 0;\n position: relative;\n background: var(--mj-bg-page);\n}\n\n/* Pane layout with an origin crumb as the FIRST element: the crumb keeps\n its fixed 32px (component host); the content sibling flex-fills. The\n height override neutralizes inline height:100% that cached wrapper\n elements carry from earlier renders (CSS !important beats inline). */\nmj-tab-container .lm_items > div > mj-record-origin-crumb,\n.direct-content-container > mj-record-origin-crumb {\n flex-shrink: 0;\n}\n\nmj-tab-container .lm_items > div > *:not(mj-record-origin-crumb),\n.direct-content-container > *:not(mj-record-origin-crumb) {\n flex: 1 1 auto;\n min-height: 0;\n height: auto !important;\n}\n\n/* Defense against visibility punch-through: `visibility: visible` on a\n DESCENDANT defeats an ancestor's visibility:hidden (unlike display:none).\n Real case: explorer-app's global `.visible { visibility: visible\n !important }` utility collides with components whose show-state class is\n named `visible` (several bespoke detail panels did this), leaving their\n overlays painted on top of the records region. The two-class specificity\n here outranks the single-class utility even with both !important. */\n.region-hidden,\n.region-hidden * {\n visibility: hidden !important;\n pointer-events: none !important;\n /* Region swaps must be INSTANT: `transition: all` rules on GL internals\n (e.g. .lm_stack) would otherwise transition `visibility` \u2014 which\n interpolates discretely, keeping the outgoing region painted on top for\n the full transition duration (a ~200ms flash of the record form over\n the destination page). */\n transition: none !important;\n}\n\n/* Direct content container for single-resource mode */\n/* Renders components directly without Golden Layout overhead */\n.direct-content-container {\n flex: 1;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n overflow: hidden;\n}\n\n.tab-content-container {\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n padding: 20px;\n}\n\n/* Context Menu */\n.context-menu {\n position: fixed;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n min-width: 150px;\n z-index: 10001;\n overflow: hidden;\n}\n\n.context-menu .context-menu-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: background 0.15s;\n /* Real <button role=\"menuitem\"> now \u2014 neutralize UA chrome */\n width: 100%;\n text-align: left;\n background: transparent;\n border: none;\n font-family: inherit;\n}\n\n/* Keyboard roving highlights like hover; ring omitted on purpose \u2014 the\n moving highlight IS the focus indicator inside a menu. */\n.context-menu .context-menu-item:focus-visible {\n outline: none;\n background: var(--mj-bg-surface-hover);\n}\n\n.context-menu .context-menu-item i {\n width: 16px;\n text-align: center;\n color: var(--mj-text-secondary);\n}\n\n.context-menu .context-menu-item:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.context-menu .context-menu-divider {\n height: 1px;\n background: var(--mj-border-default);\n margin: 4px 0;\n}\n\n/* Context menu item variants */\n.context-menu-item.new-item i { color: var(--mj-brand-primary); }\n.context-menu-item.new-item { font-weight: 500; }\n.context-menu-item.disabled { color: var(--mj-text-disabled); cursor: default; }\n.context-menu-item.disabled:hover { background: transparent; }\n.context-menu-item.disabled i { color: var(--mj-text-disabled); }\n.context-menu-item .check { margin-left: auto; color: var(--mj-status-success); font-size: 12px; }\n\n/* Override Golden Layout styles */\n/* Global overrides */\n\n/* Ensure GL root container fills available space */\nmj-tab-container .lm_goldenlayout {\n width: 100% !important;\n height: 100% !important;\n}\n\n/* Ensure the root layout item fills space */\nmj-tab-container .lm_root {\n width: 100% !important;\n height: 100% !important;\n}\n\n/* Ensure proper box-sizing for all GL layout elements */\nmj-tab-container .lm_item,\nmj-tab-container .lm_content,\nmj-tab-container .lm_stack,\nmj-tab-container .lm_row,\nmj-tab-container .lm_column {\n box-sizing: border-box !important;\n}\n\n/* Ensure layout items don't overflow */\nmj-tab-container .lm_item {\n overflow: hidden !important;\n}\n\n/* SPLIT panes get a subtle frame so side-by-side content doesn't bleed\n together (single-pane layouts stay frameless). \"Adjacent to a splitter\"\n is exactly and only the split case \u2014 any orientation, any nesting. */\nmj-tab-container .lm_stack:has(+ .lm_splitter),\nmj-tab-container .lm_splitter + .lm_stack {\n border: 1px solid var(--mj-border-default) !important;\n}\n\n/* Fix for .lm_items - the content container inside stacks */\n/* This is separate from .lm_item - it holds the actual tab content */\nmj-tab-container .lm_items {\n width: 100% !important;\n height: calc(100% - 38px) !important; /* Account for header height (38px) */\n box-sizing: border-box !important;\n position: relative !important;\n}\n\n/* When tabs are maximized, no header visible */\nmj-tab-container .lm_stack.lm_maximised > .lm_items {\n height: 100% !important;\n}\n\n/* Target the anonymous ComponentItem div inside lm_items (has no class) */\n/* Created in golden-layout/src/ts/items/component-item.ts:51 without a class */\n/* NOTE: Do NOT set display here - GL uses display:none to hide inactive tabs */\nmj-tab-container .lm_items > div {\n width: 100% !important;\n height: 100% !important;\n box-sizing: border-box !important;\n flex-direction: column !important;\n}\n\n/* Only apply flex display to the active/visible tab content div */\nmj-tab-container .lm_items > div:not([style*=\"display: none\"]) {\n display: flex !important;\n}\n\n/* Clearfix for float-based row layout - GL uses float:left for horizontal panes */\nmj-tab-container .lm_row::after {\n content: \"\" !important;\n display: table !important;\n clear: both !important;\n}\n\n/* Force content children to respect parent bounds (GL sets pixel widths inline) */\nmj-tab-container .lm_content > * {\n max-width: 100% !important;\n width: 100% !important;\n}\n\nmj-tab-container .lm_content {\n background: var(--mj-bg-page) !important;\n display: flex !important;\n flex-direction: column !important;\n height: 100% !important;\n width: 100% !important;\n}\n\nmj-tab-container .lm_item_container {\n background: var(--mj-bg-page) !important;\n}\n\n/* Tab content wrapper - allow scrolling */\n.tab-content-wrapper {\n overflow: auto !important;\n}\n\n/* Make tabs larger and easier to click */\nmj-tab-container .lm_header {\n height: 38px !important;\n padding-top: 2px !important;\n padding-left: 4px !important;\n background: var(--mj-bg-surface-sunken) !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n overflow: visible !important;\n box-sizing: border-box !important;\n}\n\n/* SCROLLING TAB STRIP (browser-tab pattern, Matt's call over GL's overflow\n dropdown): tabs keep natural width and the strip scrolls horizontally.\n Works with settingsConfig()'s effectively-infinite tabOverlapAllowance \u2014\n GL then never re-homes tabs to its dropdown, only writes inline zIndex +\n negative marginLeft, both neutralized here. Scrollbar hidden per the\n browser-tab convention; wheel input is translated to horizontal scroll by\n GoldenLayoutManager.onStripWheel, and activation scrolls the tab into view. */\nmj-tab-container .lm_tabs {\n height: 36px !important;\n left: 0;\n right: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n}\n\nmj-tab-container .lm_tabs::-webkit-scrollbar {\n display: none;\n}\n\n/* Strip nudge arrows \u2014 the VISIBLE overflow affordance (created by\n GoldenLayoutManager.updateStripNudges, one pair per header, [hidden]\n unless that direction has more tabs). The gradient doubles as the\n \"content continues\" edge fade. */\nmj-tab-container .mj-strip-nudge {\n position: absolute;\n top: 0;\n height: 36px;\n width: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n padding: 0;\n margin: 0;\n z-index: 3; /* above tabs (z 1/2) within the header context */\n font-size: 11px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n}\n\nmj-tab-container .mj-strip-nudge[hidden] {\n display: none;\n}\n\nmj-tab-container .mj-strip-nudge--left {\n left: 0;\n background: linear-gradient(to right, var(--mj-bg-surface-sunken) 55%, transparent);\n justify-content: flex-start;\n padding-left: 6px;\n}\n\nmj-tab-container .mj-strip-nudge--right {\n right: 0;\n background: linear-gradient(to left, var(--mj-bg-surface-sunken) 55%, transparent);\n justify-content: flex-end;\n padding-right: 6px;\n}\n\nmj-tab-container .mj-strip-nudge:hover {\n color: var(--mj-text-primary);\n}\n\nmj-tab-container .mj-strip-nudge:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: -2px;\n}\n\n/* Hide Golden Layout WINDOW controls (popout/maximise/stack-close). The\n scrolling strip replaces GL's lm_tabdropdown overflow menu entirely (it\n never activates with the infinite overlap allowance). */\nmj-tab-container .lm_controls .lm_popout,\nmj-tab-container .lm_controls .lm_maximise,\nmj-tab-container .lm_controls .lm_close {\n display: none !important;\n}\n\nmj-tab-container .lm_header .lm_tab {\n /* Flex centering: the type-icon slot (and any future adornment) must sit\n on the tab's vertical center \u2014 inline baseline alignment inside the\n 35px line-height text line pushed it ~15px low. */\n /* FULL FLEX FLOW (Matt's refactor): [type icon] [title] [pin] [close] are\n ordinary flex siblings \u2014 no absolute anchoring, no padding reservations,\n no vertical transforms. gap owns horizontal rhythm; align-items owns\n vertical centering for every child. */\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n padding: 0 9px !important;\n font-size: 13px !important;\n height: 35px !important;\n /* Scrolling strip: tabs are flex items of .lm_tabs \u2014 never let them\n shrink to \"fit\" (that's what the strip's scroll is for), and zero out\n the negative overlap margins GL writes inline when tabs overflow. */\n flex: 0 0 auto !important;\n margin-left: 0 !important;\n line-height: 35px !important;\n box-sizing: border-box !important;\n cursor: pointer !important;\n user-select: none !important;\n background: transparent !important;\n border: none !important;\n border-bottom: 1px solid var(--mj-border-default) !important;\n transition: all 0.15s ease !important;\n position: relative !important;\n z-index: 1 !important;\n margin-right: 1px !important;\n}\n\n/* Pipe separators between INACTIVE tabs (browser-tab pattern): a short\n centered divider on each tab's right edge establishes separation without\n boxing every tab. Suppressed around the ACTIVE tab (its raised card has\n real edges), around the hovered tab, and after the last tab. */\nmj-tab-container .lm_header .lm_tab::after {\n content: '' !important;\n position: absolute !important;\n right: -1px !important;\n top: 50% !important;\n transform: translateY(-50%) !important;\n width: 1px !important;\n height: 16px !important;\n background: var(--mj-border-strong) !important;\n}\n\nmj-tab-container .lm_header .lm_tab.lm_active::after,\nmj-tab-container .lm_header .lm_tab:has(+ .lm_tab.lm_active)::after,\nmj-tab-container .lm_header .lm_tab:hover::after,\nmj-tab-container .lm_header .lm_tab:has(+ .lm_tab:hover)::after,\nmj-tab-container .lm_header .lm_tab:last-child::after {\n content: none !important;\n}\n\n/* Type-icon slot (Matt's tab design, 2026-07-29): every tab leads with its\n TYPE icon tinted in the app color \u2014 entity icon for records, nav-item/app\n icon for pages. The old 3px app-color left-edge bar is GONE; the icon\n tint carries app identity now. Hovering the TAB swaps the icon to an\n ellipsis: the slot is the visible \"this tab has actions\" affordance \u2014\n clicking it opens the tab-actions menu (same menu as right-click). */\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot {\n display: inline-flex !important;\n align-items: center !important;\n justify-content: center !important;\n /* 24px = WCAG 2.2 AA minimum pointer target (SC 2.5.8); glyph stays 12px */\n width: 24px !important;\n height: 24px !important;\n border-radius: 5px !important;\n flex-shrink: 0 !important;\n cursor: pointer !important;\n /* The slot is a real <button> now \u2014 neutralize UA button chrome */\n background: transparent !important;\n border: none !important;\n padding: 0 !important;\n font: inherit !important;\n color: inherit !important;\n}\n\n/* Keyboard parity with hover: focused slot shows the dots + house focus\n ring (outline idiom \u2014 GL headers clip box-shadows). */\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:focus-visible {\n outline: 2px solid var(--mj-border-focus) !important;\n outline-offset: -2px !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:focus-visible .mj-tab-type-ico {\n display: none !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:focus-visible .mj-tab-dots {\n display: inline-block !important;\n}\n/* GL's base stylesheet styles EVERY `i` inside a tab as its legacy 2x19px\n absolutely-positioned corner decoration (.lm_header .lm_tab i) \u2014 which\n turns our icon elements into slivers the glyph overflows. Restore normal\n flow for the slot's icons. */\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot i {\n position: static !important;\n width: auto !important;\n height: auto !important;\n}\n\nmj-tab-container .lm_header .lm_tab .mj-tab-type-ico {\n color: var(--app-color, var(--mj-text-muted)) !important;\n font-size: 12px !important;\n line-height: 1 !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-dots {\n display: none !important;\n color: var(--mj-text-secondary) !important;\n font-size: 12px !important;\n line-height: 1 !important;\n}\nmj-tab-container .lm_header .lm_tab:hover .mj-tab-type-ico {\n display: none !important;\n}\nmj-tab-container .lm_header .lm_tab:hover .mj-tab-dots {\n display: inline-block !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:hover {\n background: var(--mj-bg-surface-hover) !important;\n}\nmj-tab-container .lm_header .lm_tab .mj-tab-type-slot:hover .mj-tab-dots {\n color: var(--mj-text-primary) !important;\n}\n\nmj-tab-container .lm_header .lm_tab:hover {\n background: var(--mj-bg-surface-hover) !important;\n}\n\n\nmj-tab-container .lm_header .lm_tab.lm_active {\n background: var(--mj-bg-surface) !important;\n height: 36px !important;\n margin-bottom: -1px !important;\n margin-right: 0 !important;\n border: 1px solid var(--mj-border-default) !important;\n border-bottom-color: var(--mj-bg-surface) !important;\n border-radius: 4px 4px 0 0 !important;\n z-index: 2 !important;\n}\n\n\nmj-tab-container .lm_title {\n cursor: pointer !important;\n user-select: none !important;\n /* In-flow flex child: normalize the inherited 35px line-height so the\n text box is glyph-height and centers identically to its siblings;\n truncate instead of colliding when GL constrains tab width. */\n line-height: normal !important;\n flex: 0 1 auto !important;\n min-width: 0 !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n white-space: nowrap !important;\n /* Glyph-overhang room: italics (unpinned tabs) paint past the last\n glyph's advance width, and overflow:hidden clips at the padding edge \u2014\n without this the final letter loses its slant. */\n padding-right: 3px !important;\n}\n\nmj-tab-container .lm_close_tab {\n position: static !important;\n order: 10 !important;\n transform: none !important;\n margin: 0 !important;\n /* 24px WCAG target; glyph stays 10px */\n width: 24px !important;\n height: 24px !important;\n border-radius: 5px !important;\n cursor: pointer !important;\n /* ALWAYS visible (Matt's call): quiet at rest, full on its own hover/focus.\n Discoverability shouldn't depend on hovering. */\n opacity: 0.55 !important;\n transition: opacity 0.15s ease !important;\n flex-shrink: 0 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n font-size: 10px !important;\n color: var(--mj-text-secondary) !important;\n}\n\nmj-tab-container .lm_close_tab:focus-visible {\n outline: 2px solid var(--mj-border-focus) !important;\n outline-offset: -2px !important;\n opacity: 1 !important;\n}\n\nmj-tab-container .lm_close_tab:hover {\n opacity: 1 !important;\n color: var(--mj-status-error) !important;\n /* background-COLOR, never the shorthand: GL's stock close was a\n background-image PNG and the shorthand silently wiped it (now it's an\n FA ::before glyph, but the discipline stands). */\n background-color: var(--mj-bg-surface-hover) !important;\n}\n\n/* Pinned tabs never show close button (the pin control replaces it) */\nmj-tab-container .lm_header .lm_tab.pinned .lm_close_tab {\n display: none !important;\n}\n\n\n"] }]
2728
- }], () => [{ type: i1.GoldenLayoutManager }, { type: i1.WorkspaceStateManager }, { type: i1.ApplicationManager }, { type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }, { type: i0.ChangeDetectorRef }], { glContainer: [{
2880
+ }], () => [{ type: i1.GoldenLayoutManager }, { type: i1.WorkspaceStateManager }, { type: i1.ApplicationManager }, { type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }, { type: i0.ChangeDetectorRef }], { GlContainer: [{
2729
2881
  type: ViewChild,
2730
2882
  args: ['glContainer', { static: false }]
2731
- }], directContentContainer: [{
2883
+ }], DirectContentContainer: [{
2732
2884
  type: ViewChild,
2733
2885
  args: ['directContentContainer', { static: false }]
2734
- }], recordsGlContainer: [{
2886
+ }], RecordsGlContainer: [{
2735
2887
  type: ViewChild,
2736
2888
  args: ['recordsGlContainer', { static: false }]
2889
+ }], FirstResourceLoadComplete: [{
2890
+ type: Output
2737
2891
  }], firstResourceLoadComplete: [{
2738
2892
  type: Output
2893
+ }], LayoutInitError: [{
2894
+ type: Output
2739
2895
  }], layoutInitError: [{
2740
2896
  type: Output
2741
2897
  }], onWindowResize: [{