@memberjunction/ng-artifacts 5.21.0 → 5.23.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.
Files changed (25) hide show
  1. package/dist/lib/artifacts.module.d.ts +3 -1
  2. package/dist/lib/artifacts.module.d.ts.map +1 -1
  3. package/dist/lib/artifacts.module.js +10 -3
  4. package/dist/lib/artifacts.module.js.map +1 -1
  5. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts +10 -0
  6. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact-type-plugin-viewer.component.js +15 -1
  8. package/dist/lib/components/artifact-type-plugin-viewer.component.js.map +1 -1
  9. package/dist/lib/components/artifact-viewer-panel.component.d.ts +24 -2
  10. package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
  11. package/dist/lib/components/artifact-viewer-panel.component.js +409 -308
  12. package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
  13. package/dist/lib/components/base-artifact-viewer.component.d.ts +16 -0
  14. package/dist/lib/components/base-artifact-viewer.component.d.ts.map +1 -1
  15. package/dist/lib/components/base-artifact-viewer.component.js +20 -0
  16. package/dist/lib/components/base-artifact-viewer.component.js.map +1 -1
  17. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +8 -1
  18. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
  19. package/dist/lib/components/plugins/component-artifact-viewer.component.js +26 -27
  20. package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
  21. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts +4 -2
  22. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts.map +1 -1
  23. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +79 -63
  24. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -1
  25. package/package.json +15 -16
@@ -27,26 +27,26 @@ function ArtifactViewerPanelComponent_Conditional_1_Conditional_5_Template(rf, c
27
27
  i0.ɵɵtextInterpolate(ctx_r1.displayDescription);
28
28
  } }
29
29
  function ArtifactViewerPanelComponent_Conditional_1_Conditional_11_Template(rf, ctx) { if (rf & 1) {
30
- i0.ɵɵelement(0, "i", 19);
30
+ i0.ɵɵelement(0, "i", 20);
31
31
  } if (rf & 2) {
32
32
  const ctx_r1 = i0.ɵɵnextContext(2);
33
33
  i0.ɵɵclassProp("open", ctx_r1.showVersionDropdown);
34
34
  } }
35
35
  function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Conditional_6_Template(rf, ctx) { if (rf & 1) {
36
- i0.ɵɵelement(0, "i", 25);
36
+ i0.ɵɵelement(0, "i", 26);
37
37
  } }
38
38
  function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
39
39
  const _r4 = i0.ɵɵgetCurrentView();
40
- i0.ɵɵelementStart(0, "div", 22);
40
+ i0.ɵɵelementStart(0, "div", 23);
41
41
  i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Template_div_click_0_listener($event) { const version_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); ctx_r1.selectVersion(version_r5); return i0.ɵɵresetView($event.stopPropagation()); });
42
- i0.ɵɵelementStart(1, "span", 23);
42
+ i0.ɵɵelementStart(1, "span", 24);
43
43
  i0.ɵɵtext(2);
44
44
  i0.ɵɵelementEnd();
45
- i0.ɵɵelementStart(3, "span", 24);
45
+ i0.ɵɵelementStart(3, "span", 25);
46
46
  i0.ɵɵtext(4);
47
47
  i0.ɵɵpipe(5, "date");
48
48
  i0.ɵɵelementEnd();
49
- i0.ɵɵconditionalCreate(6, ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Conditional_6_Template, 1, 0, "i", 25);
49
+ i0.ɵɵconditionalCreate(6, ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Conditional_6_Template, 1, 0, "i", 26);
50
50
  i0.ɵɵelementEnd();
51
51
  } if (rf & 2) {
52
52
  const version_r5 = ctx.$implicit;
@@ -61,9 +61,9 @@ function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Templat
61
61
  } }
62
62
  function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
63
63
  const _r3 = i0.ɵɵgetCurrentView();
64
- i0.ɵɵelementStart(0, "div", 20);
64
+ i0.ɵɵelementStart(0, "div", 21);
65
65
  i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r3); return i0.ɵɵresetView($event.stopPropagation()); });
66
- i0.ɵɵrepeaterCreate(1, ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Template, 7, 8, "div", 21, _forTrack0);
66
+ i0.ɵɵrepeaterCreate(1, ArtifactViewerPanelComponent_Conditional_1_Conditional_12_For_2_Template, 7, 8, "div", 22, _forTrack0);
67
67
  i0.ɵɵelementEnd();
68
68
  } if (rf & 2) {
69
69
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -72,8 +72,15 @@ function ArtifactViewerPanelComponent_Conditional_1_Conditional_12_Template(rf,
72
72
  } }
73
73
  function ArtifactViewerPanelComponent_Conditional_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
74
74
  const _r6 = i0.ɵɵgetCurrentView();
75
- i0.ɵɵelementStart(0, "button", 26);
76
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_13_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onSaveToLibrary()); });
75
+ i0.ɵɵelementStart(0, "button", 27);
76
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_13_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.pluginViewer == null ? null : ctx_r1.pluginViewer.AskUserForFeedback()); });
77
+ i0.ɵɵelement(1, "i", 28);
78
+ i0.ɵɵelementEnd();
79
+ } }
80
+ function ArtifactViewerPanelComponent_Conditional_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
81
+ const _r7 = i0.ɵɵgetCurrentView();
82
+ i0.ɵɵelementStart(0, "button", 29);
83
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_14_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onSaveToLibrary()); });
77
84
  i0.ɵɵelement(1, "i");
78
85
  i0.ɵɵelementEnd();
79
86
  } if (rf & 2) {
@@ -83,17 +90,17 @@ function ArtifactViewerPanelComponent_Conditional_1_Conditional_13_Template(rf,
83
90
  i0.ɵɵadvance();
84
91
  i0.ɵɵclassMap(ctx_r1.isInCollection ? "fas fa-bookmark" : "far fa-bookmark");
85
92
  } }
86
- function ArtifactViewerPanelComponent_Conditional_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
87
- const _r7 = i0.ɵɵgetCurrentView();
88
- i0.ɵɵelementStart(0, "button", 27);
89
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_14_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onShare()); });
90
- i0.ɵɵelement(1, "i", 28);
91
- i0.ɵɵelementEnd();
92
- } }
93
93
  function ArtifactViewerPanelComponent_Conditional_1_Conditional_15_Template(rf, ctx) { if (rf & 1) {
94
94
  const _r8 = i0.ɵɵgetCurrentView();
95
- i0.ɵɵelementStart(0, "button", 29);
96
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_15_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onMaximizeToggle()); });
95
+ i0.ɵɵelementStart(0, "button", 30);
96
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_15_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onShare()); });
97
+ i0.ɵɵelement(1, "i", 31);
98
+ i0.ɵɵelementEnd();
99
+ } }
100
+ function ArtifactViewerPanelComponent_Conditional_1_Conditional_16_Template(rf, ctx) { if (rf & 1) {
101
+ const _r9 = i0.ɵɵgetCurrentView();
102
+ i0.ɵɵelementStart(0, "button", 32);
103
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_16_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onMaximizeToggle()); });
97
104
  i0.ɵɵelement(1, "i", 7);
98
105
  i0.ɵɵelementEnd();
99
106
  } if (rf & 2) {
@@ -102,11 +109,11 @@ function ArtifactViewerPanelComponent_Conditional_1_Conditional_15_Template(rf,
102
109
  i0.ɵɵadvance();
103
110
  i0.ɵɵproperty("ngClass", ctx_r1.isMaximized ? "fa-compress-arrows-alt" : "fa-arrows-left-right");
104
111
  } }
105
- function ArtifactViewerPanelComponent_Conditional_1_Conditional_16_Template(rf, ctx) { if (rf & 1) {
106
- const _r9 = i0.ɵɵgetCurrentView();
107
- i0.ɵɵelementStart(0, "button", 30);
108
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_16_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onClose()); });
109
- i0.ɵɵelement(1, "i", 31);
112
+ function ArtifactViewerPanelComponent_Conditional_1_Conditional_17_Template(rf, ctx) { if (rf & 1) {
113
+ const _r10 = i0.ɵɵgetCurrentView();
114
+ i0.ɵɵelementStart(0, "button", 33);
115
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_1_Conditional_17_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onClose()); });
116
+ i0.ɵɵelement(1, "i", 34);
110
117
  i0.ɵɵelementEnd();
111
118
  } }
112
119
  function ArtifactViewerPanelComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
@@ -126,15 +133,16 @@ function ArtifactViewerPanelComponent_Conditional_1_Template(rf, ctx) { if (rf &
126
133
  i0.ɵɵconditionalCreate(11, ArtifactViewerPanelComponent_Conditional_1_Conditional_11_Template, 1, 2, "i", 13);
127
134
  i0.ɵɵconditionalCreate(12, ArtifactViewerPanelComponent_Conditional_1_Conditional_12_Template, 3, 0, "div", 14);
128
135
  i0.ɵɵelementEnd();
129
- i0.ɵɵconditionalCreate(13, ArtifactViewerPanelComponent_Conditional_1_Conditional_13_Template, 2, 5, "button", 15);
130
- i0.ɵɵconditionalCreate(14, ArtifactViewerPanelComponent_Conditional_1_Conditional_14_Template, 2, 0, "button", 16);
131
- i0.ɵɵconditionalCreate(15, ArtifactViewerPanelComponent_Conditional_1_Conditional_15_Template, 2, 2, "button", 17);
132
- i0.ɵɵconditionalCreate(16, ArtifactViewerPanelComponent_Conditional_1_Conditional_16_Template, 2, 0, "button", 18);
136
+ i0.ɵɵconditionalCreate(13, ArtifactViewerPanelComponent_Conditional_1_Conditional_13_Template, 2, 0, "button", 15);
137
+ i0.ɵɵconditionalCreate(14, ArtifactViewerPanelComponent_Conditional_1_Conditional_14_Template, 2, 5, "button", 16);
138
+ i0.ɵɵconditionalCreate(15, ArtifactViewerPanelComponent_Conditional_1_Conditional_15_Template, 2, 0, "button", 17);
139
+ i0.ɵɵconditionalCreate(16, ArtifactViewerPanelComponent_Conditional_1_Conditional_16_Template, 2, 2, "button", 18);
140
+ i0.ɵɵconditionalCreate(17, ArtifactViewerPanelComponent_Conditional_1_Conditional_17_Template, 2, 0, "button", 19);
133
141
  i0.ɵɵelementEnd()();
134
142
  } if (rf & 2) {
135
143
  const ctx_r1 = i0.ɵɵnextContext();
136
144
  i0.ɵɵadvance(3);
137
- i0.ɵɵproperty("ngClass", ctx_r1.getArtifactIcon());
145
+ i0.ɵɵproperty("ngClass", ctx_r1.artifactIcon);
138
146
  i0.ɵɵadvance();
139
147
  i0.ɵɵtextInterpolate1(" ", ctx_r1.displayName, " ");
140
148
  i0.ɵɵadvance();
@@ -148,24 +156,26 @@ function ArtifactViewerPanelComponent_Conditional_1_Template(rf, ctx) { if (rf &
148
156
  i0.ɵɵadvance();
149
157
  i0.ɵɵconditional(ctx_r1.showVersionDropdown ? 12 : -1);
150
158
  i0.ɵɵadvance();
151
- i0.ɵɵconditional(ctx_r1.showSaveToCollection ? 13 : -1);
159
+ i0.ɵɵconditional((ctx_r1.pluginViewer == null ? null : ctx_r1.pluginViewer.SupportsFeedback) ? 13 : -1);
160
+ i0.ɵɵadvance();
161
+ i0.ɵɵconditional(ctx_r1.showSaveToCollection ? 14 : -1);
152
162
  i0.ɵɵadvance();
153
- i0.ɵɵconditional(ctx_r1.canShare ? 14 : -1);
163
+ i0.ɵɵconditional(ctx_r1.canShare ? 15 : -1);
154
164
  i0.ɵɵadvance();
155
- i0.ɵɵconditional(ctx_r1.showMaximizeButton ? 15 : -1);
165
+ i0.ɵɵconditional(ctx_r1.showMaximizeButton ? 16 : -1);
156
166
  i0.ɵɵadvance();
157
- i0.ɵɵconditional(ctx_r1.showCloseButton ? 16 : -1);
167
+ i0.ɵɵconditional(ctx_r1.showCloseButton ? 17 : -1);
158
168
  } }
159
169
  function ArtifactViewerPanelComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
160
170
  i0.ɵɵelementStart(0, "div", 3);
161
- i0.ɵɵelement(1, "i", 32);
171
+ i0.ɵɵelement(1, "i", 35);
162
172
  i0.ɵɵelementStart(2, "span");
163
173
  i0.ɵɵtext(3, "Loading artifact...");
164
174
  i0.ɵɵelementEnd()();
165
175
  } }
166
176
  function ArtifactViewerPanelComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
167
177
  i0.ɵɵelementStart(0, "div", 4);
168
- i0.ɵɵelement(1, "i", 33);
178
+ i0.ɵɵelement(1, "i", 36);
169
179
  i0.ɵɵelementStart(2, "span");
170
180
  i0.ɵɵtext(3);
171
181
  i0.ɵɵelementEnd()();
@@ -177,29 +187,29 @@ function ArtifactViewerPanelComponent_Conditional_4_Template(rf, ctx) { if (rf &
177
187
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
178
188
  i0.ɵɵelement(0, "i");
179
189
  } if (rf & 2) {
180
- const tab_r11 = i0.ɵɵnextContext().$implicit;
190
+ const tab_r12 = i0.ɵɵnextContext().$implicit;
181
191
  const ctx_r1 = i0.ɵɵnextContext(3);
182
- i0.ɵɵclassMap(ctx_r1.GetTabIcon(tab_r11));
192
+ i0.ɵɵclassMap(ctx_r1.GetTabIcon(tab_r12));
183
193
  } }
184
194
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
185
- const _r10 = i0.ɵɵgetCurrentView();
186
- i0.ɵɵelementStart(0, "button", 48);
187
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Template_button_click_0_listener() { const tab_r11 = i0.ɵɵrestoreView(_r10).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SetActiveTab(tab_r11)); });
188
- i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Conditional_1_Template, 1, 2, "i", 49);
195
+ const _r11 = i0.ɵɵgetCurrentView();
196
+ i0.ɵɵelementStart(0, "button", 51);
197
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Template_button_click_0_listener() { const tab_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.SetActiveTab(tab_r12)); });
198
+ i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Conditional_1_Template, 1, 2, "i", 52);
189
199
  i0.ɵɵtext(2);
190
200
  i0.ɵɵelementEnd();
191
201
  } if (rf & 2) {
192
- const tab_r11 = ctx.$implicit;
202
+ const tab_r12 = ctx.$implicit;
193
203
  const ctx_r1 = i0.ɵɵnextContext(3);
194
- i0.ɵɵclassProp("active", ctx_r1.activeTab === tab_r11.toLowerCase());
204
+ i0.ɵɵclassProp("active", ctx_r1.activeTab === tab_r12.toLowerCase());
195
205
  i0.ɵɵadvance();
196
- i0.ɵɵconditional(ctx_r1.GetTabIcon(tab_r11) ? 1 : -1);
206
+ i0.ɵɵconditional(ctx_r1.GetTabIcon(tab_r12) ? 1 : -1);
197
207
  i0.ɵɵadvance();
198
- i0.ɵɵtextInterpolate1(" ", tab_r11, " ");
208
+ i0.ɵɵtextInterpolate1(" ", tab_r12, " ");
199
209
  } }
200
210
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_1_Template(rf, ctx) { if (rf & 1) {
201
- i0.ɵɵelementStart(0, "div", 35);
202
- i0.ɵɵrepeaterCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Template, 3, 4, "button", 47, i0.ɵɵrepeaterTrackByIdentity);
211
+ i0.ɵɵelementStart(0, "div", 38);
212
+ i0.ɵɵrepeaterCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_1_For_2_Template, 3, 4, "button", 50, i0.ɵɵrepeaterTrackByIdentity);
203
213
  i0.ɵɵelementEnd();
204
214
  } if (rf & 2) {
205
215
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -207,9 +217,9 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_1_Template(rf, c
207
217
  i0.ɵɵrepeater(ctx_r1.allTabs);
208
218
  } }
209
219
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template(rf, ctx) { if (rf & 1) {
210
- const _r12 = i0.ɵɵgetCurrentView();
211
- i0.ɵɵelementStart(0, "div", 50)(1, "mj-artifact-type-plugin-viewer", 51);
212
- i0.ɵɵlistener("openEntityRecord", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_openEntityRecord_1_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onOpenEntityRecord($event)); })("navigationRequest", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_navigationRequest_1_listener($event) { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNavigationRequest($event)); })("pluginLoaded", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_pluginLoaded_1_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onPluginLoaded()); })("tabsChanged", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_tabsChanged_1_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onTabsChanged()); });
220
+ const _r13 = i0.ɵɵgetCurrentView();
221
+ i0.ɵɵelementStart(0, "div", 53)(1, "mj-artifact-type-plugin-viewer", 54);
222
+ i0.ɵɵlistener("openEntityRecord", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_openEntityRecord_1_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onOpenEntityRecord($event)); })("navigationRequest", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_navigationRequest_1_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onNavigationRequest($event)); })("pluginLoaded", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_pluginLoaded_1_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onPluginLoaded()); })("tabsChanged", function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template_mj_artifact_type_plugin_viewer_tabsChanged_1_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onTabsChanged()); });
213
223
  i0.ɵɵelementEnd()();
214
224
  } if (rf & 2) {
215
225
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -218,8 +228,8 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template(rf, c
218
228
  i0.ɵɵproperty("artifactVersion", ctx_r1.artifactVersion)("artifactTypeName", ctx_r1.artifactTypeName)("contentType", ctx_r1.contentType)("readonly", true);
219
229
  } }
220
230
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
221
- i0.ɵɵelementStart(0, "div", 57);
222
- i0.ɵɵelement(1, "mj-markdown", 59);
231
+ i0.ɵɵelementStart(0, "div", 60);
232
+ i0.ɵɵelement(1, "mj-markdown", 62);
223
233
  i0.ɵɵelementEnd();
224
234
  } if (rf & 2) {
225
235
  const ctx_r1 = i0.ɵɵnextContext(4);
@@ -227,31 +237,31 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_
227
237
  i0.ɵɵproperty("data", ctx_r1.displayMarkdown)("enableCollapsibleHeadings", true)("enableLineNumbers", true)("enableSmartypants", true)("enableHtml", true);
228
238
  } }
229
239
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Conditional_8_Template(rf, ctx) { if (rf & 1) {
230
- i0.ɵɵelement(0, "div", 58);
240
+ i0.ɵɵelement(0, "div", 61);
231
241
  } if (rf & 2) {
232
242
  const ctx_r1 = i0.ɵɵnextContext(4);
233
243
  i0.ɵɵproperty("innerHTML", ctx_r1.displayHtml, i0.ɵɵsanitizeHtml);
234
244
  } }
235
245
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
236
- const _r13 = i0.ɵɵgetCurrentView();
237
- i0.ɵɵelementStart(0, "div", 52)(1, "button", 53);
238
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onPrintDisplayContent()); });
239
- i0.ɵɵelement(2, "i", 54);
246
+ const _r14 = i0.ɵɵgetCurrentView();
247
+ i0.ɵɵelementStart(0, "div", 55)(1, "button", 56);
248
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onPrintDisplayContent()); });
249
+ i0.ɵɵelement(2, "i", 57);
240
250
  i0.ɵɵtext(3, " Print ");
241
251
  i0.ɵɵelementEnd();
242
- i0.ɵɵelementStart(4, "button", 55);
243
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r13); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onCopyDisplayContent()); });
244
- i0.ɵɵelement(5, "i", 56);
252
+ i0.ɵɵelementStart(4, "button", 58);
253
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onCopyDisplayContent()); });
254
+ i0.ɵɵelement(5, "i", 59);
245
255
  i0.ɵɵtext(6, " Copy ");
246
256
  i0.ɵɵelementEnd()();
247
- i0.ɵɵconditionalCreate(7, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Conditional_7_Template, 2, 5, "div", 57)(8, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Conditional_8_Template, 1, 1, "div", 58);
257
+ i0.ɵɵconditionalCreate(7, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Conditional_7_Template, 2, 5, "div", 60)(8, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Conditional_8_Template, 1, 1, "div", 61);
248
258
  } if (rf & 2) {
249
259
  const ctx_r1 = i0.ɵɵnextContext(3);
250
260
  i0.ɵɵadvance(7);
251
261
  i0.ɵɵconditional(ctx_r1.displayMarkdown ? 7 : ctx_r1.displayHtml ? 8 : -1);
252
262
  } }
253
263
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
254
- i0.ɵɵelementStart(0, "div", 38);
264
+ i0.ɵɵelementStart(0, "div", 41);
255
265
  i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Conditional_1_Template, 9, 1);
256
266
  i0.ɵɵelementEnd();
257
267
  } if (rf & 2) {
@@ -260,7 +270,7 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Template(rf, c
260
270
  i0.ɵɵconditional(ctx_r1.displayMarkdown || ctx_r1.displayHtml ? 1 : -1);
261
271
  } }
262
272
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_29_Template(rf, ctx) { if (rf & 1) {
263
- i0.ɵɵelementStart(0, "div", 42)(1, "label");
273
+ i0.ɵɵelementStart(0, "div", 45)(1, "label");
264
274
  i0.ɵɵtext(2, "Artifact Description");
265
275
  i0.ɵɵelementEnd();
266
276
  i0.ɵɵelementStart(3, "span");
@@ -272,7 +282,7 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_29_Template(rf,
272
282
  i0.ɵɵtextInterpolate(ctx_r1.artifact.Description);
273
283
  } }
274
284
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_30_Template(rf, ctx) { if (rf & 1) {
275
- i0.ɵɵelementStart(0, "div", 42)(1, "label");
285
+ i0.ɵɵelementStart(0, "div", 45)(1, "label");
276
286
  i0.ɵɵtext(2, "Version Description");
277
287
  i0.ɵɵelementEnd();
278
288
  i0.ɵɵelementStart(3, "span");
@@ -288,34 +298,34 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Conditi
288
298
  i0.ɵɵtext(1);
289
299
  i0.ɵɵelementEnd();
290
300
  } if (rf & 2) {
291
- const attr_r14 = i0.ɵɵnextContext().$implicit;
301
+ const attr_r15 = i0.ɵɵnextContext().$implicit;
292
302
  i0.ɵɵadvance();
293
- i0.ɵɵtextInterpolate(attr_r14.Value);
303
+ i0.ɵɵtextInterpolate(attr_r15.Value);
294
304
  } }
295
305
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Conditional_4_Template(rf, ctx) { if (rf & 1) {
296
- i0.ɵɵelementStart(0, "span", 62);
306
+ i0.ɵɵelementStart(0, "span", 65);
297
307
  i0.ɵɵtext(1, "Empty");
298
308
  i0.ɵɵelementEnd();
299
309
  } }
300
310
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Template(rf, ctx) { if (rf & 1) {
301
- i0.ɵɵelementStart(0, "div", 61)(1, "label");
311
+ i0.ɵɵelementStart(0, "div", 64)(1, "label");
302
312
  i0.ɵɵtext(2);
303
313
  i0.ɵɵelementEnd();
304
- i0.ɵɵconditionalCreate(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Conditional_3_Template, 2, 1, "span")(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Conditional_4_Template, 2, 0, "span", 62);
314
+ i0.ɵɵconditionalCreate(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Conditional_3_Template, 2, 1, "span")(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Conditional_4_Template, 2, 0, "span", 65);
305
315
  i0.ɵɵelementEnd();
306
316
  } if (rf & 2) {
307
- const attr_r14 = ctx.$implicit;
317
+ const attr_r15 = ctx.$implicit;
308
318
  i0.ɵɵadvance(2);
309
- i0.ɵɵtextInterpolate(attr_r14.Name);
319
+ i0.ɵɵtextInterpolate(attr_r15.Name);
310
320
  i0.ɵɵadvance();
311
- i0.ɵɵconditional(attr_r14.Value ? 3 : 4);
321
+ i0.ɵɵconditional(attr_r15.Value ? 3 : 4);
312
322
  } }
313
323
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_31_Template(rf, ctx) { if (rf & 1) {
314
- i0.ɵɵelementStart(0, "div", 43)(1, "h4");
324
+ i0.ɵɵelementStart(0, "div", 46)(1, "h4");
315
325
  i0.ɵɵtext(2, "Version Attributes");
316
326
  i0.ɵɵelementEnd();
317
- i0.ɵɵelementStart(3, "div", 60);
318
- i0.ɵɵrepeaterCreate(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Template, 5, 2, "div", 61, _forTrack0);
327
+ i0.ɵɵelementStart(3, "div", 63);
328
+ i0.ɵɵrepeaterCreate(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_For_5_Template, 5, 2, "div", 64, _forTrack0);
319
329
  i0.ɵɵelementEnd()();
320
330
  } if (rf & 2) {
321
331
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -323,41 +333,41 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_31_Template(rf,
323
333
  i0.ɵɵrepeater(ctx_r1.filteredAttributes);
324
334
  } }
325
335
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
326
- i0.ɵɵelement(0, "i", 66);
336
+ i0.ɵɵelement(0, "i", 69);
327
337
  } }
328
338
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Conditional_3_Template(rf, ctx) { if (rf & 1) {
329
- i0.ɵɵelement(0, "i", 67);
339
+ i0.ɵɵelement(0, "i", 70);
330
340
  } }
331
341
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Template(rf, ctx) { if (rf & 1) {
332
- const _r15 = i0.ɵɵgetCurrentView();
333
- i0.ɵɵelementStart(0, "div", 64);
334
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Template_div_click_0_listener() { const link_r16 = i0.ɵɵrestoreView(_r15).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(link_r16.hasAccess ? ctx_r1.onNavigateToLink(link_r16) : null); });
335
- i0.ɵɵelementStart(1, "div", 65);
336
- i0.ɵɵconditionalCreate(2, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Conditional_2_Template, 1, 0, "i", 66)(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Conditional_3_Template, 1, 0, "i", 67);
342
+ const _r16 = i0.ɵɵgetCurrentView();
343
+ i0.ɵɵelementStart(0, "div", 67);
344
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Template_div_click_0_listener() { const link_r17 = i0.ɵɵrestoreView(_r16).$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(link_r17.hasAccess ? ctx_r1.onNavigateToLink(link_r17) : null); });
345
+ i0.ɵɵelementStart(1, "div", 68);
346
+ i0.ɵɵconditionalCreate(2, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Conditional_2_Template, 1, 0, "i", 69)(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Conditional_3_Template, 1, 0, "i", 70);
337
347
  i0.ɵɵelementEnd();
338
- i0.ɵɵelementStart(4, "div", 68)(5, "div", 69);
348
+ i0.ɵɵelementStart(4, "div", 71)(5, "div", 72);
339
349
  i0.ɵɵtext(6);
340
350
  i0.ɵɵelementEnd();
341
- i0.ɵɵelementStart(7, "div", 70);
351
+ i0.ɵɵelementStart(7, "div", 73);
342
352
  i0.ɵɵtext(8);
343
353
  i0.ɵɵelementEnd()();
344
- i0.ɵɵelementStart(9, "div", 71);
345
- i0.ɵɵelement(10, "i", 72);
354
+ i0.ɵɵelementStart(9, "div", 74);
355
+ i0.ɵɵelement(10, "i", 75);
346
356
  i0.ɵɵelementEnd()();
347
357
  } if (rf & 2) {
348
- const link_r16 = ctx.$implicit;
349
- i0.ɵɵclassProp("disabled", !link_r16.hasAccess)("clickable", link_r16.hasAccess);
350
- i0.ɵɵproperty("title", link_r16.hasAccess ? "Click to open" : "No access");
358
+ const link_r17 = ctx.$implicit;
359
+ i0.ɵɵclassProp("disabled", !link_r17.hasAccess)("clickable", link_r17.hasAccess);
360
+ i0.ɵɵproperty("title", link_r17.hasAccess ? "Click to open" : "No access");
351
361
  i0.ɵɵadvance(2);
352
- i0.ɵɵconditional(link_r16.type === "conversation" ? 2 : 3);
362
+ i0.ɵɵconditional(link_r17.type === "conversation" ? 2 : 3);
353
363
  i0.ɵɵadvance(4);
354
- i0.ɵɵtextInterpolate(link_r16.name);
364
+ i0.ɵɵtextInterpolate(link_r17.name);
355
365
  i0.ɵɵadvance(2);
356
- i0.ɵɵtextInterpolate(link_r16.type === "conversation" ? "Conversation" : "Collection");
366
+ i0.ɵɵtextInterpolate(link_r17.type === "conversation" ? "Conversation" : "Collection");
357
367
  } }
358
368
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_Template(rf, ctx) { if (rf & 1) {
359
- i0.ɵɵelementStart(0, "div", 45);
360
- i0.ɵɵrepeaterCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Template, 11, 8, "div", 63, _forTrack1);
369
+ i0.ɵɵelementStart(0, "div", 48);
370
+ i0.ɵɵrepeaterCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_For_2_Template, 11, 8, "div", 66, _forTrack1);
361
371
  i0.ɵɵelementEnd();
362
372
  } if (rf & 2) {
363
373
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -365,8 +375,8 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_33_Template(rf,
365
375
  i0.ɵɵrepeater(ctx_r1.linksToShow);
366
376
  } }
367
377
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_34_Template(rf, ctx) { if (rf & 1) {
368
- i0.ɵɵelementStart(0, "div", 46);
369
- i0.ɵɵelement(1, "i", 73);
378
+ i0.ɵɵelementStart(0, "div", 49);
379
+ i0.ɵɵelement(1, "i", 76);
370
380
  i0.ɵɵelementStart(2, "p");
371
381
  i0.ɵɵtext(3, "No links available");
372
382
  i0.ɵɵelementEnd()();
@@ -375,8 +385,8 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0
375
385
  i0.ɵɵelementContainer(0);
376
386
  } }
377
387
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0_Template(rf, ctx) { if (rf & 1) {
378
- i0.ɵɵelementStart(0, "div", 74);
379
- i0.ɵɵtemplate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0_ng_container_1_Template, 1, 0, "ng-container", 75);
388
+ i0.ɵɵelementStart(0, "div", 77);
389
+ i0.ɵɵtemplate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0_ng_container_1_Template, 1, 0, "ng-container", 78);
380
390
  i0.ɵɵelementEnd();
381
391
  } if (rf & 2) {
382
392
  const ctx_r1 = i0.ɵɵnextContext(3);
@@ -384,62 +394,62 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0
384
394
  i0.ɵɵproperty("ngComponentOutlet", ctx)("ngComponentOutletInputs", ctx_r1.GetComponentInputs(ctx_r1.activeTab));
385
395
  } }
386
396
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_1_Template(rf, ctx) { if (rf & 1) {
387
- i0.ɵɵelementStart(0, "div", 77);
388
- i0.ɵɵelement(1, "mj-markdown", 59);
397
+ i0.ɵɵelementStart(0, "div", 80);
398
+ i0.ɵɵelement(1, "mj-markdown", 62);
389
399
  i0.ɵɵelementEnd();
390
400
  } if (rf & 2) {
391
- const tabData_r17 = i0.ɵɵnextContext();
401
+ const tabData_r18 = i0.ɵɵnextContext();
392
402
  i0.ɵɵadvance();
393
- i0.ɵɵproperty("data", tabData_r17.content)("enableCollapsibleHeadings", true)("enableLineNumbers", true)("enableSmartypants", true)("enableHtml", true);
403
+ i0.ɵɵproperty("data", tabData_r18.content)("enableCollapsibleHeadings", true)("enableLineNumbers", true)("enableSmartypants", true)("enableHtml", true);
394
404
  } }
395
405
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_2_Template(rf, ctx) { if (rf & 1) {
396
- const _r18 = i0.ɵɵgetCurrentView();
397
- i0.ɵɵelementStart(0, "div", 78)(1, "div", 82)(2, "button", 83);
398
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_2_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onCopyToClipboard()); });
399
- i0.ɵɵelement(3, "i", 56);
406
+ const _r19 = i0.ɵɵgetCurrentView();
407
+ i0.ɵɵelementStart(0, "div", 81)(1, "div", 85)(2, "button", 86);
408
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_2_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onCopyToClipboard()); });
409
+ i0.ɵɵelement(3, "i", 59);
400
410
  i0.ɵɵtext(4, " Copy ");
401
411
  i0.ɵɵelementEnd()();
402
- i0.ɵɵelementStart(5, "div", 84);
403
- i0.ɵɵelement(6, "mj-code-editor", 85);
412
+ i0.ɵɵelementStart(5, "div", 87);
413
+ i0.ɵɵelement(6, "mj-code-editor", 88);
404
414
  i0.ɵɵelementEnd()();
405
415
  } if (rf & 2) {
406
- const tabData_r17 = i0.ɵɵnextContext();
416
+ const tabData_r18 = i0.ɵɵnextContext();
407
417
  i0.ɵɵadvance(6);
408
- i0.ɵɵproperty("value", tabData_r17.content)("language", "json")("readonly", true)("lineWrapping", true);
418
+ i0.ɵɵproperty("value", tabData_r18.content)("language", "json")("readonly", true)("lineWrapping", true);
409
419
  } }
410
420
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_3_Template(rf, ctx) { if (rf & 1) {
411
- const _r19 = i0.ɵɵgetCurrentView();
412
- i0.ɵɵelementStart(0, "div", 79)(1, "div", 86)(2, "button", 87);
413
- i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_3_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r19); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onCopyToClipboard()); });
414
- i0.ɵɵelement(3, "i", 56);
421
+ const _r20 = i0.ɵɵgetCurrentView();
422
+ i0.ɵɵelementStart(0, "div", 82)(1, "div", 89)(2, "button", 90);
423
+ i0.ɵɵlistener("click", function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_3_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r20); const ctx_r1 = i0.ɵɵnextContext(5); return i0.ɵɵresetView(ctx_r1.onCopyToClipboard()); });
424
+ i0.ɵɵelement(3, "i", 59);
415
425
  i0.ɵɵtext(4, " Copy ");
416
426
  i0.ɵɵelementEnd()();
417
- i0.ɵɵelementStart(5, "div", 88);
418
- i0.ɵɵelement(6, "mj-code-editor", 85);
427
+ i0.ɵɵelementStart(5, "div", 91);
428
+ i0.ɵɵelement(6, "mj-code-editor", 88);
419
429
  i0.ɵɵelementEnd()();
420
430
  } if (rf & 2) {
421
- const tabData_r17 = i0.ɵɵnextContext();
431
+ const tabData_r18 = i0.ɵɵnextContext();
422
432
  i0.ɵɵadvance(6);
423
- i0.ɵɵproperty("value", tabData_r17.content)("language", tabData_r17.language || "typescript")("readonly", true)("lineWrapping", true);
433
+ i0.ɵɵproperty("value", tabData_r18.content)("language", tabData_r18.language || "typescript")("readonly", true)("lineWrapping", true);
424
434
  } }
425
435
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_4_Template(rf, ctx) { if (rf & 1) {
426
- i0.ɵɵelement(0, "div", 80);
436
+ i0.ɵɵelement(0, "div", 83);
427
437
  } if (rf & 2) {
428
- const tabData_r17 = i0.ɵɵnextContext();
429
- i0.ɵɵproperty("innerHTML", tabData_r17.content, i0.ɵɵsanitizeHtml);
438
+ const tabData_r18 = i0.ɵɵnextContext();
439
+ i0.ɵɵproperty("innerHTML", tabData_r18.content, i0.ɵɵsanitizeHtml);
430
440
  } }
431
441
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_5_Template(rf, ctx) { if (rf & 1) {
432
- i0.ɵɵelementStart(0, "pre", 81);
442
+ i0.ɵɵelementStart(0, "pre", 84);
433
443
  i0.ɵɵtext(1);
434
444
  i0.ɵɵelementEnd();
435
445
  } if (rf & 2) {
436
- const tabData_r17 = i0.ɵɵnextContext();
446
+ const tabData_r18 = i0.ɵɵnextContext();
437
447
  i0.ɵɵadvance();
438
- i0.ɵɵtextInterpolate(tabData_r17.content);
448
+ i0.ɵɵtextInterpolate(tabData_r18.content);
439
449
  } }
440
450
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
441
- i0.ɵɵelementStart(0, "div", 76);
442
- i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_1_Template, 2, 5, "div", 77)(2, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_2_Template, 7, 4, "div", 78)(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_3_Template, 7, 4, "div", 79)(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_4_Template, 1, 1, "div", 80)(5, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_5_Template, 2, 1, "pre", 81);
451
+ i0.ɵɵelementStart(0, "div", 79);
452
+ i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_1_Template, 2, 5, "div", 80)(2, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_2_Template, 7, 4, "div", 81)(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_3_Template, 7, 4, "div", 82)(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_4_Template, 1, 1, "div", 83)(5, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Case_5_Template, 2, 1, "pre", 84);
443
453
  i0.ɵɵelementEnd();
444
454
  } if (rf & 2) {
445
455
  let tmp_5_0;
@@ -447,58 +457,58 @@ function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1
447
457
  i0.ɵɵconditional((tmp_5_0 = ctx.type) === "markdown" ? 1 : tmp_5_0 === "json" ? 2 : tmp_5_0 === "code" ? 3 : tmp_5_0 === "html" ? 4 : tmp_5_0 === "plaintext" ? 5 : -1);
448
458
  } }
449
459
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Template(rf, ctx) { if (rf & 1) {
450
- i0.ɵɵconditionalCreate(0, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Template, 6, 1, "div", 76);
460
+ i0.ɵɵconditionalCreate(0, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Conditional_0_Template, 6, 1, "div", 79);
451
461
  } if (rf & 2) {
452
462
  let tmp_3_0;
453
463
  const ctx_r1 = i0.ɵɵnextContext(3);
454
464
  i0.ɵɵconditional((tmp_3_0 = ctx_r1.GetTabContent(ctx_r1.activeTab)) ? 0 : -1, tmp_3_0);
455
465
  } }
456
466
  function ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Template(rf, ctx) { if (rf & 1) {
457
- i0.ɵɵconditionalCreate(0, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0_Template, 2, 2, "div", 74)(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Template, 1, 1);
467
+ i0.ɵɵconditionalCreate(0, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_0_Template, 2, 2, "div", 77)(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Conditional_1_Template, 1, 1);
458
468
  } if (rf & 2) {
459
469
  let tmp_2_0;
460
470
  const ctx_r1 = i0.ɵɵnextContext(2);
461
471
  i0.ɵɵconditional((tmp_2_0 = ctx_r1.GetComponentTabType(ctx_r1.activeTab)) ? 0 : 1, tmp_2_0);
462
472
  } }
463
473
  function ArtifactViewerPanelComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
464
- i0.ɵɵelementStart(0, "div", 34);
465
- i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_1_Template, 3, 0, "div", 35);
466
- i0.ɵɵelementStart(2, "div", 36);
467
- i0.ɵɵconditionalCreate(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template, 2, 6, "div", 37);
468
- i0.ɵɵconditionalCreate(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Template, 2, 1, "div", 38);
469
- i0.ɵɵelementStart(5, "div", 39)(6, "div", 40)(7, "div", 41)(8, "label");
474
+ i0.ɵɵelementStart(0, "div", 37);
475
+ i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_5_Conditional_1_Template, 3, 0, "div", 38);
476
+ i0.ɵɵelementStart(2, "div", 39);
477
+ i0.ɵɵconditionalCreate(3, ArtifactViewerPanelComponent_Conditional_5_Conditional_3_Template, 2, 6, "div", 40);
478
+ i0.ɵɵconditionalCreate(4, ArtifactViewerPanelComponent_Conditional_5_Conditional_4_Template, 2, 1, "div", 41);
479
+ i0.ɵɵelementStart(5, "div", 42)(6, "div", 43)(7, "div", 44)(8, "label");
470
480
  i0.ɵɵtext(9, "Type");
471
481
  i0.ɵɵelementEnd();
472
482
  i0.ɵɵelementStart(10, "span");
473
483
  i0.ɵɵtext(11);
474
484
  i0.ɵɵelementEnd()();
475
- i0.ɵɵelementStart(12, "div", 41)(13, "label");
485
+ i0.ɵɵelementStart(12, "div", 44)(13, "label");
476
486
  i0.ɵɵtext(14, "Version");
477
487
  i0.ɵɵelementEnd();
478
488
  i0.ɵɵelementStart(15, "span");
479
489
  i0.ɵɵtext(16);
480
490
  i0.ɵɵelementEnd()();
481
- i0.ɵɵelementStart(17, "div", 41)(18, "label");
491
+ i0.ɵɵelementStart(17, "div", 44)(18, "label");
482
492
  i0.ɵɵtext(19, "Created");
483
493
  i0.ɵɵelementEnd();
484
494
  i0.ɵɵelementStart(20, "span");
485
495
  i0.ɵɵtext(21);
486
496
  i0.ɵɵpipe(22, "date");
487
497
  i0.ɵɵelementEnd()();
488
- i0.ɵɵelementStart(23, "div", 41)(24, "label");
498
+ i0.ɵɵelementStart(23, "div", 44)(24, "label");
489
499
  i0.ɵɵtext(25, "Updated");
490
500
  i0.ɵɵelementEnd();
491
501
  i0.ɵɵelementStart(26, "span");
492
502
  i0.ɵɵtext(27);
493
503
  i0.ɵɵpipe(28, "date");
494
504
  i0.ɵɵelementEnd()();
495
- i0.ɵɵconditionalCreate(29, ArtifactViewerPanelComponent_Conditional_5_Conditional_29_Template, 5, 1, "div", 42);
496
- i0.ɵɵconditionalCreate(30, ArtifactViewerPanelComponent_Conditional_5_Conditional_30_Template, 5, 1, "div", 42);
505
+ i0.ɵɵconditionalCreate(29, ArtifactViewerPanelComponent_Conditional_5_Conditional_29_Template, 5, 1, "div", 45);
506
+ i0.ɵɵconditionalCreate(30, ArtifactViewerPanelComponent_Conditional_5_Conditional_30_Template, 5, 1, "div", 45);
497
507
  i0.ɵɵelementEnd();
498
- i0.ɵɵconditionalCreate(31, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_Template, 6, 0, "div", 43);
508
+ i0.ɵɵconditionalCreate(31, ArtifactViewerPanelComponent_Conditional_5_Conditional_31_Template, 6, 0, "div", 46);
499
509
  i0.ɵɵelementEnd();
500
- i0.ɵɵelementStart(32, "div", 44);
501
- i0.ɵɵconditionalCreate(33, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_Template, 3, 0, "div", 45)(34, ArtifactViewerPanelComponent_Conditional_5_Conditional_34_Template, 4, 0, "div", 46);
510
+ i0.ɵɵelementStart(32, "div", 47);
511
+ i0.ɵɵconditionalCreate(33, ArtifactViewerPanelComponent_Conditional_5_Conditional_33_Template, 3, 0, "div", 48)(34, ArtifactViewerPanelComponent_Conditional_5_Conditional_34_Template, 4, 0, "div", 49);
502
512
  i0.ɵɵelementEnd();
503
513
  i0.ɵɵconditionalCreate(35, ArtifactViewerPanelComponent_Conditional_5_Conditional_35_Template, 2, 1);
504
514
  i0.ɵɵelementEnd()();
@@ -724,20 +734,23 @@ export class ArtifactViewerPanelComponent {
724
734
  if (changes['versionNumber'] && !changes['versionNumber'].firstChange) {
725
735
  const newVersionNumber = changes['versionNumber'].currentValue;
726
736
  if (newVersionNumber != null) {
727
- // Check if we already have this version loaded (avoid reload if possible)
737
+ // Check if we have metadata for this version (allVersions has lightweight metadata)
728
738
  const targetVersion = this.allVersions.find(v => v.VersionNumber === newVersionNumber);
729
739
  if (targetVersion) {
730
- // Just switch to the version we already have
731
- this.artifactVersion = targetVersion;
732
740
  this.selectedVersionNumber = targetVersion.VersionNumber || 1;
733
- this.jsonContent = this.FormatJSON(targetVersion.Content || '{}');
734
- // Load version attributes
735
- await this.loadVersionAttributes();
736
- // Reload collection associations for this version
737
- await this.loadCollectionAssociations();
738
- // Reload links data
739
- await this.loadLinksData();
740
- this.cdr.detectChanges(); // zone.js 0.15: async chain doesn't trigger CD
741
+ // Load full content for the selected version
742
+ const fullVersion = await this.loadVersionContent(targetVersion.ID);
743
+ if (fullVersion) {
744
+ this.artifactVersion = fullVersion;
745
+ this.jsonContent = this.FormatJSON(fullVersion.Content || '{}');
746
+ }
747
+ // Load attributes and collection data in parallel
748
+ await Promise.all([
749
+ this.loadVersionAttributes(),
750
+ this.loadCollectionAssociations(),
751
+ this.loadLinksData()
752
+ ]);
753
+ this.cdr.detectChanges();
741
754
  }
742
755
  else {
743
756
  // Need to reload to get this version (shouldn't normally happen)
@@ -757,56 +770,81 @@ export class ArtifactViewerPanelComponent {
757
770
  // Clear links data from previous artifact to prevent stale Links tab
758
771
  this.clearLinksData();
759
772
  const md = new Metadata();
760
- // Load artifact
761
- this.artifact = await md.GetEntityObject('MJ: Artifacts', this.currentUser);
762
- const loaded = await this.artifact.Load(this.artifactId);
773
+ // Load artifact — assign to local first to avoid mid-cycle icon flicker
774
+ const artifactEntity = await md.GetEntityObject('MJ: Artifacts', this.currentUser);
775
+ const loaded = await artifactEntity.Load(this.artifactId);
763
776
  if (!loaded) {
764
777
  this.error = 'Failed to load artifact';
765
778
  return;
766
779
  }
767
- // Load artifact type to check for DriverClass
768
- await this.loadArtifactType();
769
- // Load ALL versions
780
+ this.artifact = artifactEntity;
781
+ // PERF: Batch load version metadata, collection associations, and conversation links
782
+ // in a single RunViews call. Content is excluded here — loaded on-demand for the selected version.
770
783
  const rv = new RunView();
771
- const result = await rv.RunView({
772
- EntityName: 'MJ: Artifact Versions',
773
- ExtraFilter: `ArtifactID='${this.artifactId}'`,
774
- OrderBy: 'VersionNumber DESC',
775
- ResultType: 'entity_object'
776
- }, this.currentUser);
777
- if (result.Success && result.Results && result.Results.length > 0) {
778
- this.allVersions = result.Results;
779
- // If target version specified, try to load it
780
- if (targetVersionNumber) {
781
- const targetVersion = this.allVersions.find(v => v.VersionNumber === targetVersionNumber);
782
- if (targetVersion) {
783
- this.artifactVersion = targetVersion;
784
- this.selectedVersionNumber = targetVersion.VersionNumber || 1;
785
- this.jsonContent = this.FormatJSON(targetVersion.Content || '{}');
786
- }
787
- else {
788
- // Target version not found, default to latest
789
- this.artifactVersion = result.Results[0];
790
- this.selectedVersionNumber = this.artifactVersion.VersionNumber || 1;
791
- this.jsonContent = this.FormatJSON(this.artifactVersion.Content || '{}');
792
- }
793
- }
794
- else {
795
- // No target version, default to latest version (first in DESC order)
796
- this.artifactVersion = result.Results[0];
797
- this.selectedVersionNumber = this.artifactVersion.VersionNumber || 1;
798
- this.jsonContent = this.FormatJSON(this.artifactVersion.Content || '{}');
784
+ const batchResults = await rv.RunViews([
785
+ {
786
+ // [0] Version metadata (lightweight — no Content field)
787
+ EntityName: 'MJ: Artifact Versions',
788
+ ExtraFilter: `ArtifactID='${this.artifactId}'`,
789
+ OrderBy: 'VersionNumber DESC',
790
+ Fields: ['ID', 'ArtifactID', 'VersionNumber', 'Name', 'Description', '__mj_CreatedAt', '__mj_UpdatedAt'],
791
+ ResultType: 'simple'
792
+ },
793
+ {
794
+ // [1] Collection associations for all versions of this artifact
795
+ EntityName: 'MJ: Collection Artifacts',
796
+ ExtraFilter: `ArtifactVersionID IN (
797
+ SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${this.artifactId}'
798
+ )`,
799
+ Fields: ['ID', 'CollectionID', 'ArtifactVersionID', 'Sequence'],
800
+ ResultType: 'simple'
801
+ },
802
+ {
803
+ // [2] Conversation detail artifact links (for Links tab)
804
+ EntityName: 'MJ: Conversation Detail Artifacts',
805
+ ExtraFilter: `ArtifactVersionID IN (
806
+ SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${this.artifactId}'
807
+ )`,
808
+ Fields: ['ID', 'ConversationDetailID', 'ArtifactVersionID'],
809
+ MaxRows: 1,
810
+ ResultType: 'simple'
799
811
  }
800
- // Load version attributes
801
- await this.loadVersionAttributes();
802
- // Load collection associations
803
- await this.loadCollectionAssociations();
804
- // Load links data
805
- await this.loadLinksData();
812
+ ], this.currentUser);
813
+ const [versionsResult, collectionsResult, convDetailResult] = batchResults;
814
+ if (!versionsResult.Success || !versionsResult.Results || versionsResult.Results.length === 0) {
815
+ this.error = 'No artifact version found';
816
+ return;
817
+ }
818
+ // Store version metadata as simple objects (used for dropdown display)
819
+ this.allVersions = versionsResult.Results;
820
+ // Determine which version to display
821
+ let selectedVersion;
822
+ if (targetVersionNumber) {
823
+ selectedVersion = versionsResult.Results.find((v) => v.VersionNumber === targetVersionNumber);
824
+ }
825
+ // Fall back to latest version (first in DESC order)
826
+ const versionToLoad = selectedVersion || versionsResult.Results[0];
827
+ this.selectedVersionNumber = versionToLoad.VersionNumber || 1;
828
+ // PERF: Start artifact type resolution and selected version content load in parallel
829
+ const [, selectedVersionEntity] = await Promise.all([
830
+ this.loadArtifactType(),
831
+ this.loadVersionContent(versionToLoad.ID)
832
+ ]);
833
+ if (selectedVersionEntity) {
834
+ this.artifactVersion = selectedVersionEntity;
835
+ this.jsonContent = this.FormatJSON(selectedVersionEntity.Content || '{}');
806
836
  }
807
837
  else {
808
- this.error = 'No artifact version found';
838
+ this.error = 'Failed to load artifact version content';
839
+ return;
809
840
  }
841
+ // PERF: Process collection and links data in parallel (uses already-fetched batch data)
842
+ await Promise.all([
843
+ this.processCollectionAssociations(collectionsResult),
844
+ this.processLinksData(collectionsResult, convDetailResult)
845
+ ]);
846
+ // Load version attributes (depends on selected version being set)
847
+ await this.loadVersionAttributes();
810
848
  }
811
849
  catch (err) {
812
850
  console.error('Error loading artifact:', err);
@@ -814,9 +852,26 @@ export class ArtifactViewerPanelComponent {
814
852
  }
815
853
  finally {
816
854
  this.isLoading = false;
855
+ this.updateArtifactIcon();
817
856
  this.cdr.detectChanges();
818
857
  }
819
858
  }
859
+ /**
860
+ * Load full content for a single version by ID.
861
+ * This avoids downloading Content for ALL versions when only one is displayed.
862
+ */
863
+ async loadVersionContent(versionId) {
864
+ try {
865
+ const md = new Metadata();
866
+ const versionEntity = await md.GetEntityObject('MJ: Artifact Versions', this.currentUser);
867
+ const loaded = await versionEntity.Load(versionId);
868
+ return loaded ? versionEntity : null;
869
+ }
870
+ catch (err) {
871
+ console.error('Error loading version content:', err);
872
+ return null;
873
+ }
874
+ }
820
875
  /**
821
876
  * Clear all links-related data to prevent stale data when switching artifacts
822
877
  */
@@ -851,7 +906,7 @@ export class ArtifactViewerPanelComponent {
851
906
  const result = await rv.RunView({
852
907
  EntityName: 'MJ: Artifact Version Attributes',
853
908
  ExtraFilter: `ArtifactVersionID='${this.artifactVersion.ID}'`,
854
- ResultType: 'entity_object'
909
+ ResultType: 'simple'
855
910
  }, this.currentUser);
856
911
  if (result.Success && result.Results) {
857
912
  this.versionAttributes = result.Results;
@@ -1003,53 +1058,73 @@ export class ArtifactViewerPanelComponent {
1003
1058
  cleaned = cleaned.replace(/\\\\n/g, '');
1004
1059
  return cleaned;
1005
1060
  }
1006
- async loadCollectionAssociations() {
1061
+ /**
1062
+ * Process pre-fetched collection association data.
1063
+ * Accepts the batch result from loadArtifact() to avoid duplicate queries.
1064
+ */
1065
+ async processCollectionAssociations(collectionsResult) {
1007
1066
  if (!this.artifactId)
1008
1067
  return;
1009
1068
  try {
1010
- const rv = new RunView();
1011
- // Load ALL collection associations for ALL versions of this artifact
1012
- const result = await rv.RunView({
1013
- EntityName: 'MJ: Collection Artifacts',
1014
- ExtraFilter: `ArtifactVersionID IN (
1015
- SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${this.artifactId}'
1016
- )`,
1017
- ResultType: 'entity_object'
1018
- }, this.currentUser);
1019
- if (result.Success && result.Results) {
1020
- this.artifactCollections = result.Results;
1021
- // Filter to get only collections containing the CURRENT version
1022
- const currentVersionId = this.artifactVersion?.ID;
1023
- if (currentVersionId) {
1024
- // Type-safe comparison: ensure both IDs are strings and match exactly
1025
- const currentIdStr = String(currentVersionId).toLowerCase();
1026
- this.currentVersionCollections = result.Results.filter(ca => {
1027
- const versionIdStr = String(ca.ArtifactVersionID || '').toLowerCase();
1028
- return versionIdStr && currentIdStr && versionIdStr === currentIdStr;
1029
- });
1030
- }
1031
- else {
1032
- this.currentVersionCollections = [];
1033
- }
1034
- // Load the primary collection details if exists
1035
- if (this.artifactCollections.length > 0) {
1036
- const collectionId = this.artifactCollections[0].CollectionID;
1069
+ // If no pre-fetched data, fetch it (used by selectVersion/saveToCollections reload)
1070
+ let collectionRows;
1071
+ if (collectionsResult?.Success && collectionsResult.Results) {
1072
+ collectionRows = collectionsResult.Results;
1073
+ }
1074
+ else {
1075
+ const rv = new RunView();
1076
+ const result = await rv.RunView({
1077
+ EntityName: 'MJ: Collection Artifacts',
1078
+ ExtraFilter: `ArtifactVersionID IN (
1079
+ SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${this.artifactId}'
1080
+ )`,
1081
+ Fields: ['ID', 'CollectionID', 'ArtifactVersionID', 'Sequence'],
1082
+ ResultType: 'simple'
1083
+ }, this.currentUser);
1084
+ collectionRows = (result.Success ? result.Results : []);
1085
+ }
1086
+ // Store as simple objects — these are read-only display data
1087
+ this.artifactCollections = collectionRows;
1088
+ // Filter to get only collections containing the CURRENT version
1089
+ const currentVersionId = this.artifactVersion?.ID;
1090
+ if (currentVersionId) {
1091
+ const currentIdStr = String(currentVersionId).toLowerCase();
1092
+ this.currentVersionCollections = collectionRows.filter(ca => {
1093
+ const versionIdStr = String(ca['ArtifactVersionID'] || ca.ArtifactVersionID || '').toLowerCase();
1094
+ return versionIdStr && currentIdStr && versionIdStr === currentIdStr;
1095
+ });
1096
+ }
1097
+ else {
1098
+ this.currentVersionCollections = [];
1099
+ }
1100
+ // Load the primary collection details if exists
1101
+ if (this.artifactCollections.length > 0) {
1102
+ const collectionId = collectionRows[0].CollectionID ||
1103
+ this.artifactCollections[0].CollectionID;
1104
+ if (collectionId) {
1037
1105
  const md = new Metadata();
1038
1106
  this.primaryCollection = await md.GetEntityObject('MJ: Collections', this.currentUser);
1039
1107
  await this.primaryCollection.Load(collectionId);
1040
1108
  }
1041
- else {
1042
- this.primaryCollection = null;
1043
- }
1109
+ }
1110
+ else {
1111
+ this.primaryCollection = null;
1044
1112
  }
1045
1113
  }
1046
1114
  catch (err) {
1047
- console.error('Error loading collection associations:', err);
1115
+ console.error('Error processing collection associations:', err);
1048
1116
  }
1049
1117
  finally {
1050
- this.cdr.detectChanges(); // zone.js 0.15: async RunView doesn't trigger CD
1118
+ this.cdr.detectChanges();
1051
1119
  }
1052
1120
  }
1121
+ /**
1122
+ * @deprecated Use processCollectionAssociations() instead. Kept as a shim for callers
1123
+ * that don't have pre-fetched data (e.g., selectVersion, saveToCollections).
1124
+ */
1125
+ async loadCollectionAssociations() {
1126
+ return this.processCollectionAssociations();
1127
+ }
1053
1128
  get isInCollection() {
1054
1129
  return this.currentVersionCollections.length > 0;
1055
1130
  }
@@ -1129,18 +1204,21 @@ export class ArtifactViewerPanelComponent {
1129
1204
  }
1130
1205
  }
1131
1206
  async selectVersion(version) {
1132
- this.artifactVersion = version;
1133
1207
  this.selectedVersionNumber = version.VersionNumber || 1;
1134
- this.jsonContent = this.FormatJSON(version.Content || '{}');
1135
1208
  this.showVersionDropdown = false;
1136
- // Load attributes for the selected version
1137
- await this.loadVersionAttributes();
1138
- // CRITICAL FIX: Reload collection associations for this version
1139
- // This ensures bookmark button and Links tab reflect the correct state
1140
- await this.loadCollectionAssociations();
1141
- // Also reload links data to update conversation/collection links
1142
- await this.loadLinksData();
1143
- this.cdr.detectChanges(); // zone.js 0.15: async chain doesn't trigger CD
1209
+ // Load full content for the selected version (allVersions only has metadata)
1210
+ const fullVersion = await this.loadVersionContent(version.ID);
1211
+ if (fullVersion) {
1212
+ this.artifactVersion = fullVersion;
1213
+ this.jsonContent = this.FormatJSON(fullVersion.Content || '{}');
1214
+ }
1215
+ // Load attributes and collection data in parallel
1216
+ await Promise.all([
1217
+ this.loadVersionAttributes(),
1218
+ this.loadCollectionAssociations(),
1219
+ this.loadLinksData()
1220
+ ]);
1221
+ this.cdr.detectChanges();
1144
1222
  }
1145
1223
  async onSaveToLibrary() {
1146
1224
  // Always show the collection picker modal
@@ -1220,9 +1298,10 @@ export class ArtifactViewerPanelComponent {
1220
1298
  }
1221
1299
  }
1222
1300
  /**
1223
- * Load links data: origin conversation and all collections containing this artifact
1301
+ * Process links data using pre-fetched batch results from loadArtifact().
1302
+ * Reuses collection data from the same batch to avoid duplicate queries.
1224
1303
  */
1225
- async loadLinksData() {
1304
+ async processLinksData(collectionsResult, convDetailResult) {
1226
1305
  if (!this.artifactId)
1227
1306
  return;
1228
1307
  // Clear old links data first to prevent stale data from previous artifact
@@ -1230,68 +1309,81 @@ export class ArtifactViewerPanelComponent {
1230
1309
  try {
1231
1310
  const md = new Metadata();
1232
1311
  const rv = new RunView();
1233
- // Load all collections containing any version of this artifact
1234
- const collArtifactsResult = await rv.RunView({
1235
- EntityName: 'MJ: Collection Artifacts',
1236
- ExtraFilter: `ArtifactVersionID IN (
1237
- SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${this.artifactId}'
1238
- )`,
1239
- ResultType: 'entity_object'
1240
- }, this.currentUser);
1241
- if (collArtifactsResult.Success && collArtifactsResult.Results) {
1242
- // Get unique collection IDs
1243
- const collectionIds = [...new Set(collArtifactsResult.Results.map(ca => ca.CollectionID))];
1244
- if (collectionIds.length > 0) {
1245
- const collectionsFilter = collectionIds.map(id => `ID='${id}'`).join(' OR ');
1246
- const collectionsResult = await rv.RunView({
1247
- EntityName: 'MJ: Collections',
1248
- ExtraFilter: collectionsFilter,
1249
- ResultType: 'entity_object'
1312
+ // Use pre-fetched collection data or fetch if not provided
1313
+ let collectionRows = [];
1314
+ if (collectionsResult?.Success && collectionsResult.Results) {
1315
+ collectionRows = collectionsResult.Results;
1316
+ }
1317
+ else {
1318
+ const result = await rv.RunView({
1319
+ EntityName: 'MJ: Collection Artifacts',
1320
+ ExtraFilter: `ArtifactVersionID IN (
1321
+ SELECT ID FROM [__mj].[vwArtifactVersions] WHERE ArtifactID='${this.artifactId}'
1322
+ )`,
1323
+ Fields: ['ID', 'CollectionID', 'ArtifactVersionID'],
1324
+ ResultType: 'simple'
1325
+ }, this.currentUser);
1326
+ collectionRows = (result.Success ? result.Results : []);
1327
+ }
1328
+ // Get unique collection IDs and load collection details
1329
+ const collectionIds = [...new Set(collectionRows.map(ca => (ca['CollectionID'] || ca.CollectionID)))].filter(Boolean);
1330
+ if (collectionIds.length > 0) {
1331
+ const collectionsFilter = collectionIds.map(id => `ID='${id}'`).join(' OR ');
1332
+ const collectionsEntityResult = await rv.RunView({
1333
+ EntityName: 'MJ: Collections',
1334
+ ExtraFilter: collectionsFilter,
1335
+ Fields: ['ID', 'Name', 'UserID', 'Description'],
1336
+ ResultType: 'simple'
1337
+ }, this.currentUser);
1338
+ if (collectionsEntityResult.Success && collectionsEntityResult.Results) {
1339
+ this.allCollections = collectionsEntityResult.Results;
1340
+ }
1341
+ }
1342
+ // Use pre-fetched conversation detail artifact data or fetch if not provided
1343
+ let convDetailRows = [];
1344
+ if (convDetailResult?.Success && convDetailResult.Results) {
1345
+ convDetailRows = convDetailResult.Results;
1346
+ }
1347
+ else {
1348
+ const versionIds = this.allVersions.map(v => v.ID);
1349
+ if (versionIds.length > 0) {
1350
+ const versionFilter = versionIds.map(id => `ArtifactVersionID='${id}'`).join(' OR ');
1351
+ const result = await rv.RunView({
1352
+ EntityName: 'MJ: Conversation Detail Artifacts',
1353
+ ExtraFilter: versionFilter,
1354
+ Fields: ['ID', 'ConversationDetailID', 'ArtifactVersionID'],
1355
+ MaxRows: 1,
1356
+ ResultType: 'simple'
1250
1357
  }, this.currentUser);
1251
- if (collectionsResult.Success && collectionsResult.Results) {
1252
- this.allCollections = collectionsResult.Results;
1253
- }
1358
+ convDetailRows = (result.Success ? result.Results : []);
1254
1359
  }
1255
1360
  }
1256
- // Load origin conversation (if artifact came from conversation)
1257
- // Artifacts are linked to conversations via ConversationDetailArtifact -> ConversationDetail -> Conversation
1258
- // Get all version IDs for this artifact
1259
- const versionIds = this.allVersions.map(v => v.ID);
1260
- if (versionIds.length > 0) {
1261
- const versionFilter = versionIds.map(id => `ArtifactVersionID='${id}'`).join(' OR ');
1262
- const convDetailArtifactsResult = await rv.RunView({
1263
- EntityName: 'MJ: Conversation Detail Artifacts',
1264
- ExtraFilter: versionFilter,
1265
- MaxRows: 1,
1266
- ResultType: 'entity_object'
1267
- }, this.currentUser);
1268
- if (convDetailArtifactsResult.Success && convDetailArtifactsResult.Results && convDetailArtifactsResult.Results.length > 0) {
1269
- const conversationDetailId = convDetailArtifactsResult.Results[0].ConversationDetailID;
1270
- const artifactVersionId = convDetailArtifactsResult.Results[0].ArtifactVersionID;
1271
- // Store which version came from the origin conversation
1272
- this.originConversationVersionId = artifactVersionId;
1273
- // Load the conversation detail to get the conversation ID
1274
- const conversationDetail = await md.GetEntityObject('MJ: Conversation Details', this.currentUser);
1275
- const detailLoaded = await conversationDetail.Load(conversationDetailId);
1276
- if (detailLoaded && conversationDetail.ConversationID) {
1277
- const conversation = await md.GetEntityObject('MJ: Conversations', this.currentUser);
1278
- const loaded = await conversation.Load(conversationDetail.ConversationID);
1279
- if (loaded) {
1280
- this.originConversation = conversation;
1281
- // Check if user has access (is owner or participant)
1282
- const userIsOwner = UUIDsEqual(conversation.UserID, this.currentUser.ID);
1283
- // Check if user is a participant
1284
- const participantResult = await rv.RunView({
1285
- EntityName: 'MJ: Conversation Details',
1286
- ExtraFilter: `ConversationID='${conversation.ID}' AND UserID='${this.currentUser.ID}'`,
1287
- MaxRows: 1,
1288
- ResultType: 'simple'
1289
- }, this.currentUser);
1290
- const userIsParticipant = participantResult.Success &&
1291
- participantResult.Results &&
1292
- participantResult.Results.length > 0;
1293
- this.hasAccessToOriginConversation = userIsOwner || userIsParticipant;
1294
- }
1361
+ // Load origin conversation if we have a link
1362
+ if (convDetailRows.length > 0) {
1363
+ const conversationDetailId = (convDetailRows[0]['ConversationDetailID'] || convDetailRows[0].ConversationDetailID);
1364
+ const artifactVersionId = (convDetailRows[0]['ArtifactVersionID'] || convDetailRows[0].ArtifactVersionID);
1365
+ this.originConversationVersionId = artifactVersionId;
1366
+ // Load conversation detail to get conversation ID
1367
+ const conversationDetail = await md.GetEntityObject('MJ: Conversation Details', this.currentUser);
1368
+ const detailLoaded = await conversationDetail.Load(conversationDetailId);
1369
+ if (detailLoaded && conversationDetail.ConversationID) {
1370
+ const conversation = await md.GetEntityObject('MJ: Conversations', this.currentUser);
1371
+ const loaded = await conversation.Load(conversationDetail.ConversationID);
1372
+ if (loaded) {
1373
+ this.originConversation = conversation;
1374
+ // Check if user has access (is owner or participant)
1375
+ const userIsOwner = UUIDsEqual(conversation.UserID, this.currentUser.ID);
1376
+ const participantResult = await rv.RunView({
1377
+ EntityName: 'MJ: Conversation Details',
1378
+ ExtraFilter: `ConversationID='${conversation.ID}' AND UserID='${this.currentUser.ID}'`,
1379
+ MaxRows: 1,
1380
+ Fields: ['ID'],
1381
+ ResultType: 'simple'
1382
+ }, this.currentUser);
1383
+ const userIsParticipant = participantResult.Success &&
1384
+ participantResult.Results &&
1385
+ participantResult.Results.length > 0;
1386
+ this.hasAccessToOriginConversation = userIsOwner || userIsParticipant;
1295
1387
  }
1296
1388
  }
1297
1389
  }
@@ -1300,9 +1392,15 @@ export class ArtifactViewerPanelComponent {
1300
1392
  console.error('Error loading links data:', error);
1301
1393
  }
1302
1394
  finally {
1303
- this.cdr.detectChanges(); // zone.js 0.15: async chain doesn't trigger CD
1395
+ this.cdr.detectChanges();
1304
1396
  }
1305
1397
  }
1398
+ /**
1399
+ * @deprecated Use processLinksData() instead. Kept as shim for callers without pre-fetched data.
1400
+ */
1401
+ async loadLinksData() {
1402
+ return this.processLinksData();
1403
+ }
1306
1404
  get linksToShow() {
1307
1405
  const links = [];
1308
1406
  // Get current version ID being viewed
@@ -1503,10 +1601,13 @@ export class ArtifactViewerPanelComponent {
1503
1601
  * Get the icon for this artifact using the centralized icon service.
1504
1602
  * Fallback priority: Plugin icon > Metadata icon > Hardcoded mapping > Generic icon
1505
1603
  */
1506
- getArtifactIcon() {
1507
- if (!this.artifact)
1508
- return 'fa-file';
1509
- return this.artifactIconService.getArtifactIcon(this.artifact);
1604
+ /** Cached icon class — set once after artifact loads to avoid mid-cycle flicker */
1605
+ artifactIcon = 'fa-file';
1606
+ /** Update the cached icon from the loaded artifact */
1607
+ updateArtifactIcon() {
1608
+ this.artifactIcon = this.artifact
1609
+ ? this.artifactIconService.getArtifactIcon(this.artifact)
1610
+ : 'fa-file';
1510
1611
  }
1511
1612
  static ɵfac = function ArtifactViewerPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ArtifactViewerPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.MJNotificationService), i0.ɵɵdirectiveInject(i2.DomSanitizer), i0.ɵɵdirectiveInject(i3.ArtifactIconService)); };
1512
1613
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ArtifactViewerPanelComponent, selectors: [["mj-artifact-viewer-panel"]], viewQuery: function ArtifactViewerPanelComponent_Query(rf, ctx) { if (rf & 1) {
@@ -1514,9 +1615,9 @@ export class ArtifactViewerPanelComponent {
1514
1615
  } if (rf & 2) {
1515
1616
  let _t;
1516
1617
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.pluginViewer = _t.first);
1517
- } }, inputs: { artifactId: "artifactId", currentUser: "currentUser", environmentId: "environmentId", versionNumber: "versionNumber", showSaveToCollection: "showSaveToCollection", showHeader: "showHeader", showTabs: "showTabs", showCloseButton: "showCloseButton", showMaximizeButton: "showMaximizeButton", refreshTrigger: "refreshTrigger", viewContext: "viewContext", contextCollectionId: "contextCollectionId", canShare: "canShare", canEdit: "canEdit", isMaximized: "isMaximized" }, outputs: { closed: "closed", saveToCollectionRequested: "saveToCollectionRequested", navigateToLink: "navigateToLink", shareRequested: "shareRequested", maximizeToggled: "maximizeToggled", openEntityRecord: "openEntityRecord", navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 6, vars: 6, consts: [[1, "artifact-viewer-panel"], [1, "panel-header"], [1, "panel-content"], [1, "loading-state"], [1, "error-state"], [1, "artifact-content-wrapper", 3, "no-tabs"], [1, "panel-header-left"], [1, "fas", 3, "ngClass"], [1, "header-description"], [1, "panel-header-right"], [1, "version-selector", 3, "click"], [1, "fas", "fa-history"], [1, "version-label"], [1, "fas", "fa-chevron-down", "dropdown-icon", 3, "open"], [1, "version-dropdown"], [1, "save-to-collection-btn", 3, "in-collection", "title"], ["title", "Share", 1, "share-btn"], [1, "maximize-btn", 3, "title"], ["title", "Close", 1, "close-btn"], [1, "fas", "fa-chevron-down", "dropdown-icon"], [1, "version-dropdown", 3, "click"], [1, "version-option", 3, "selected"], [1, "version-option", 3, "click"], [1, "version-number"], [1, "version-date"], [1, "fas", "fa-check"], [1, "save-to-collection-btn", 3, "click", "title"], ["title", "Share", 1, "share-btn", 3, "click"], [1, "fas", "fa-share-nodes"], [1, "maximize-btn", 3, "click", "title"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fas", "fa-times"], [1, "fas", "fa-spinner", "fa-spin"], [1, "fas", "fa-exclamation-triangle"], [1, "artifact-content-wrapper"], [1, "tab-navigation"], [1, "tab-content"], [1, "plugin-container", 3, "plugin-hidden"], [1, "display-content"], [1, "details-content"], [1, "artifact-meta"], [1, "meta-item"], [1, "meta-item", "full-width"], [1, "attributes-section"], [1, "links-container"], [1, "links-section"], [1, "empty-state"], [1, "tab-btn", 3, "active"], [1, "tab-btn", 3, "click"], [3, "class"], [1, "plugin-container"], [3, "openEntityRecord", "navigationRequest", "pluginLoaded", "tabsChanged", "artifactVersion", "artifactTypeName", "contentType", "readonly"], [1, "display-toolbar"], ["title", "Print", 1, "btn-icon", 3, "click"], [1, "fas", "fa-print"], ["title", "Copy Content", 1, "btn-icon", 3, "click"], [1, "fas", "fa-copy"], [1, "markdown-content"], [1, "html-content", 3, "innerHTML"], [3, "data", "enableCollapsibleHeadings", "enableLineNumbers", "enableSmartypants", "enableHtml"], [1, "attributes-list"], [1, "attribute-item"], [1, "attribute-empty-pill"], [1, "link-item", 3, "disabled", "clickable", "title"], [1, "link-item", 3, "click", "title"], [1, "link-icon"], [1, "fas", "fa-comments"], [1, "fas", "fa-folder"], [1, "link-content"], [1, "link-name"], [1, "link-type"], [1, "link-actions"], [1, "fas", "fa-arrow-right"], [1, "fas", "fa-link"], [1, "component-tab-content"], [4, "ngComponentOutlet", "ngComponentOutletInputs"], [1, "dynamic-tab-content"], [1, "markdown-viewer"], [1, "json-viewer"], [1, "code-viewer"], [1, "html-viewer", 3, "innerHTML"], [1, "plaintext-viewer"], [1, "json-toolbar"], ["title", "Copy JSON", 1, "btn-icon", 3, "click"], [1, "json-editor-container"], [2, "width", "100%", "height", "100%", 3, "value", "language", "readonly", "lineWrapping"], [1, "code-toolbar"], ["title", "Copy Code", 1, "btn-icon", 3, "click"], [1, "code-editor-container"]], template: function ArtifactViewerPanelComponent_Template(rf, ctx) { if (rf & 1) {
1618
+ } }, inputs: { artifactId: "artifactId", currentUser: "currentUser", environmentId: "environmentId", versionNumber: "versionNumber", showSaveToCollection: "showSaveToCollection", showHeader: "showHeader", showTabs: "showTabs", showCloseButton: "showCloseButton", showMaximizeButton: "showMaximizeButton", refreshTrigger: "refreshTrigger", viewContext: "viewContext", contextCollectionId: "contextCollectionId", canShare: "canShare", canEdit: "canEdit", isMaximized: "isMaximized" }, outputs: { closed: "closed", saveToCollectionRequested: "saveToCollectionRequested", navigateToLink: "navigateToLink", shareRequested: "shareRequested", maximizeToggled: "maximizeToggled", openEntityRecord: "openEntityRecord", navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 6, vars: 6, consts: [[1, "artifact-viewer-panel"], [1, "panel-header"], [1, "panel-content"], [1, "loading-state"], [1, "error-state"], [1, "artifact-content-wrapper", 3, "no-tabs"], [1, "panel-header-left"], [1, "fas", 3, "ngClass"], [1, "header-description"], [1, "panel-header-right"], [1, "version-selector", 3, "click"], [1, "fas", "fa-history"], [1, "version-label"], [1, "fas", "fa-chevron-down", "dropdown-icon", 3, "open"], [1, "version-dropdown"], ["title", "Inspect & rate components", 1, "feedback-btn"], [1, "save-to-collection-btn", 3, "in-collection", "title"], ["title", "Share", 1, "share-btn"], [1, "maximize-btn", 3, "title"], ["title", "Close", 1, "close-btn"], [1, "fas", "fa-chevron-down", "dropdown-icon"], [1, "version-dropdown", 3, "click"], [1, "version-option", 3, "selected"], [1, "version-option", 3, "click"], [1, "version-number"], [1, "version-date"], [1, "fas", "fa-check"], ["title", "Inspect & rate components", 1, "feedback-btn", 3, "click"], [1, "fas", "fa-star-half-stroke"], [1, "save-to-collection-btn", 3, "click", "title"], ["title", "Share", 1, "share-btn", 3, "click"], [1, "fas", "fa-share-nodes"], [1, "maximize-btn", 3, "click", "title"], ["title", "Close", 1, "close-btn", 3, "click"], [1, "fas", "fa-times"], [1, "fas", "fa-spinner", "fa-spin"], [1, "fas", "fa-exclamation-triangle"], [1, "artifact-content-wrapper"], [1, "tab-navigation"], [1, "tab-content"], [1, "plugin-container", 3, "plugin-hidden"], [1, "display-content"], [1, "details-content"], [1, "artifact-meta"], [1, "meta-item"], [1, "meta-item", "full-width"], [1, "attributes-section"], [1, "links-container"], [1, "links-section"], [1, "empty-state"], [1, "tab-btn", 3, "active"], [1, "tab-btn", 3, "click"], [3, "class"], [1, "plugin-container"], [3, "openEntityRecord", "navigationRequest", "pluginLoaded", "tabsChanged", "artifactVersion", "artifactTypeName", "contentType", "readonly"], [1, "display-toolbar"], ["title", "Print", 1, "btn-icon", 3, "click"], [1, "fas", "fa-print"], ["title", "Copy Content", 1, "btn-icon", 3, "click"], [1, "fas", "fa-copy"], [1, "markdown-content"], [1, "html-content", 3, "innerHTML"], [3, "data", "enableCollapsibleHeadings", "enableLineNumbers", "enableSmartypants", "enableHtml"], [1, "attributes-list"], [1, "attribute-item"], [1, "attribute-empty-pill"], [1, "link-item", 3, "disabled", "clickable", "title"], [1, "link-item", 3, "click", "title"], [1, "link-icon"], [1, "fas", "fa-comments"], [1, "fas", "fa-folder"], [1, "link-content"], [1, "link-name"], [1, "link-type"], [1, "link-actions"], [1, "fas", "fa-arrow-right"], [1, "fas", "fa-link"], [1, "component-tab-content"], [4, "ngComponentOutlet", "ngComponentOutletInputs"], [1, "dynamic-tab-content"], [1, "markdown-viewer"], [1, "json-viewer"], [1, "code-viewer"], [1, "html-viewer", 3, "innerHTML"], [1, "plaintext-viewer"], [1, "json-toolbar"], ["title", "Copy JSON", 1, "btn-icon", 3, "click"], [1, "json-editor-container"], [2, "width", "100%", "height", "100%", 3, "value", "language", "readonly", "lineWrapping"], [1, "code-toolbar"], ["title", "Copy Code", 1, "btn-icon", 3, "click"], [1, "code-editor-container"]], template: function ArtifactViewerPanelComponent_Template(rf, ctx) { if (rf & 1) {
1518
1619
  i0.ɵɵelementStart(0, "div", 0);
1519
- i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_1_Template, 17, 12, "div", 1);
1620
+ i0.ɵɵconditionalCreate(1, ArtifactViewerPanelComponent_Conditional_1_Template, 18, 13, "div", 1);
1520
1621
  i0.ɵɵelementStart(2, "div", 2);
1521
1622
  i0.ɵɵconditionalCreate(3, ArtifactViewerPanelComponent_Conditional_3_Template, 4, 0, "div", 3);
1522
1623
  i0.ɵɵconditionalCreate(4, ArtifactViewerPanelComponent_Conditional_4_Template, 4, 1, "div", 4);
@@ -1532,11 +1633,11 @@ export class ArtifactViewerPanelComponent {
1532
1633
  i0.ɵɵconditional(ctx.error ? 4 : -1);
1533
1634
  i0.ɵɵadvance();
1534
1635
  i0.ɵɵconditional(!ctx.isLoading && !ctx.error && ctx.artifact ? 5 : -1);
1535
- } }, dependencies: [i4.NgClass, i4.NgComponentOutlet, i5.MarkdownComponent, i6.CodeEditorComponent, i7.ArtifactTypePluginViewerComponent, i4.DatePipe], styles: [".artifact-viewer-panel[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.panel-header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n margin-right: 16px;\n}\n\n.panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.header-description[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: normal;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.version-selector[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.version-selector.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.version-selector.clickable[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n}\n\n.version-selector[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.version-selector[_ngcontent-%COMP%] .dropdown-icon[_ngcontent-%COMP%] {\n margin-left: 2px;\n transition: transform 0.2s;\n}\n\n.version-selector[_ngcontent-%COMP%] .dropdown-icon.open[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n.version-label[_ngcontent-%COMP%] {\n font-family: monospace;\n}\n\n.version-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 200px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n z-index: 1000;\n overflow: hidden;\n}\n\n.version-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n cursor: pointer;\n transition: background 0.15s;\n font-size: 13px;\n}\n\n.version-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.version-option.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.version-option[_ngcontent-%COMP%] .version-number[_ngcontent-%COMP%] {\n font-family: monospace;\n font-weight: 600;\n min-width: 35px;\n}\n\n.version-option[_ngcontent-%COMP%] .version-date[_ngcontent-%COMP%] {\n flex: 1;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.version-option[_ngcontent-%COMP%] i.fa-check[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n margin-left: auto;\n}\n\n.save-to-collection-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.save-to-collection-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.save-to-collection-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.save-to-collection-btn.in-collection[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.save-to-collection-btn.in-collection[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.share-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.share-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.share-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.maximize-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.maximize-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.maximize-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.close-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n.artifact-content-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n}\n\n.artifact-meta[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 16px;\n margin-bottom: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.meta-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.meta-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.artifact-description[_ngcontent-%COMP%] {\n padding: 12px;\n margin-bottom: 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n border-radius: 4px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.json-viewer[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n padding: 6px 12px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: all 0.2s;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-icon.btn-primary[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.btn-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.modal-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n}\n\n.modal-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 20px;\n overflow-y: auto;\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.form-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-select[_ngcontent-%COMP%], \n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.2s;\n}\n\n.form-select[_ngcontent-%COMP%]:focus, \n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.divider[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin: 24px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.divider[_ngcontent-%COMP%]::before, \n.divider[_ngcontent-%COMP%]::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.divider[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n padding: 0 12px;\n}\n\n.create-collection-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.create-collection-row[_ngcontent-%COMP%] .form-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n}\n\n.btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n}\n\n\n\n.tab-navigation[_ngcontent-%COMP%] {\n display: flex;\n gap: 0;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 16px;\n background: var(--mj-bg-surface);\n}\n\n.tab-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 12px 20px;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.tab-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.tab-btn.active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n width: 100%;\n box-sizing: border-box;\n margin-bottom: 5px;\n min-width: 0;\n min-height: 0;\n}\n\n\n\n.plugin-container[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.plugin-container.plugin-hidden[_ngcontent-%COMP%], \n.tab-hidden[_ngcontent-%COMP%] {\n display: none;\n}\n\n\n\n.plugin-container[_ngcontent-%COMP%] mj-artifact-type-plugin-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n}\n\n.display-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n min-height: 0;\n min-width: 0;\n padding: 7px;\n}\n\n.display-toolbar[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n right: 12px;\n display: flex;\n gap: 8px;\n z-index: 10;\n}\n\n.markdown-content[_ngcontent-%COMP%], \n.html-content[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n line-height: 1.6;\n width: 100%;\n padding: 20px 10px 5px 20px; \n\n box-sizing: border-box;\n overflow: auto;\n min-height: 0;\n}\n\n.details-content[_ngcontent-%COMP%] {\n padding: 20px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.details-content[_ngcontent-%COMP%] .artifact-meta[_ngcontent-%COMP%] {\n margin-bottom: 0;\n padding: 20px;\n}\n\n.details-content[_ngcontent-%COMP%] .meta-item.full-width[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.attributes-section[_ngcontent-%COMP%] {\n margin-top: 24px;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.attributes-section[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.attributes-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 16px;\n}\n\n.attribute-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.attribute-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.attribute-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-word;\n}\n\n.attribute-empty-pill[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n font-size: 11px;\n font-weight: 500;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n\n\n.links-container[_ngcontent-%COMP%] {\n padding: 20px;\n}\n\n.links-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.link-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n transition: all 0.15s;\n}\n\n.link-item.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.link-item.clickable[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n background: var(--mj-bg-surface-sunken);\n}\n\n.link-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.link-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.link-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.link-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-brand-primary);\n}\n\n.link-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.link-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.link-type[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.link-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.link-actions[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n transition: all 0.15s;\n}\n\n.link-item.clickable[_ngcontent-%COMP%]:hover .link-actions[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n}\n\n.links-container[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-disabled);\n text-align: center;\n}\n\n.links-container[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.links-container[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.dynamic-tab-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n padding: 16px;\n}\n\n\n\n.component-tab-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: auto;\n padding: 16px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n line-height: 1.6;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .markdown-viewer[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .markdown-viewer[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin-top: 24px;\n margin-bottom: 12px;\n font-weight: 600;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] { font-size: 24px; }\n.markdown-viewer[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] { font-size: 20px; }\n.markdown-viewer[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { font-size: 18px; }\n\n.markdown-viewer[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .markdown-viewer[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n padding-left: 24px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 3px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n overflow-x: auto;\n margin-bottom: 12px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: none;\n padding: 0;\n}\n\n.code-viewer[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.code-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.code-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.plaintext-viewer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n font-family: 'Courier New', monospace;\n font-size: 13px;\n white-space: pre-wrap;\n}\n\n.html-viewer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n}\n\n\n\n@media (max-width: 768px) {\n \n\n .artifact-viewer-panel[_ngcontent-%COMP%] {\n border-top: 3px solid var(--mj-brand-primary);\n position: relative;\n }\n\n \n\n .artifact-viewer-panel[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n top: -8px;\n left: 0;\n right: 0;\n height: 8px;\n background: var(--mj-brand-secondary);\n }\n\n .tab-navigation[_ngcontent-%COMP%] {\n padding: 0 8px;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n }\n\n .tab-navigation[_ngcontent-%COMP%]::-webkit-scrollbar {\n display: none;\n }\n\n .tab-btn[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .panel-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .dynamic-tab-content[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .markdown-viewer[_ngcontent-%COMP%] {\n padding: 12px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .tab-navigation[_ngcontent-%COMP%] {\n padding: 0 4px;\n }\n\n .tab-btn[_ngcontent-%COMP%] {\n padding: 8px 10px;\n font-size: 11px;\n gap: 4px;\n }\n\n .tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .panel-header[_ngcontent-%COMP%] {\n padding: 8px;\n }\n\n .dynamic-tab-content[_ngcontent-%COMP%] {\n padding: 8px;\n }\n\n .markdown-viewer[_ngcontent-%COMP%] {\n padding: 8px;\n }\n}"] });
1636
+ } }, dependencies: [i4.NgClass, i4.NgComponentOutlet, i5.MarkdownComponent, i6.CodeEditorComponent, i7.ArtifactTypePluginViewerComponent, i4.DatePipe], styles: [".artifact-viewer-panel[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.panel-header-left[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n margin-right: 16px;\n}\n\n.panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.header-description[_ngcontent-%COMP%] {\n margin: 4px 0 0 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: normal;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.version-selector[_ngcontent-%COMP%] {\n position: relative;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.version-selector.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.version-selector.clickable[_ngcontent-%COMP%]:hover {\n background: var(--mj-border-default);\n}\n\n.version-selector[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n}\n\n.version-selector[_ngcontent-%COMP%] .dropdown-icon[_ngcontent-%COMP%] {\n margin-left: 2px;\n transition: transform 0.2s;\n}\n\n.version-selector[_ngcontent-%COMP%] .dropdown-icon.open[_ngcontent-%COMP%] {\n transform: rotate(180deg);\n}\n\n.version-label[_ngcontent-%COMP%] {\n font-family: monospace;\n}\n\n.version-dropdown[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 200px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n z-index: 1000;\n overflow: hidden;\n}\n\n.version-option[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n cursor: pointer;\n transition: background 0.15s;\n font-size: 13px;\n}\n\n.version-option[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.version-option.selected[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.version-option[_ngcontent-%COMP%] .version-number[_ngcontent-%COMP%] {\n font-family: monospace;\n font-weight: 600;\n min-width: 35px;\n}\n\n.version-option[_ngcontent-%COMP%] .version-date[_ngcontent-%COMP%] {\n flex: 1;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.version-option[_ngcontent-%COMP%] i.fa-check[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n margin-left: auto;\n}\n\n.feedback-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.feedback-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.feedback-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.save-to-collection-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.save-to-collection-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.save-to-collection-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.save-to-collection-btn.in-collection[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.save-to-collection-btn.in-collection[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.share-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.share-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.share-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.maximize-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.maximize-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.maximize-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.close-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n.artifact-content-wrapper[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n}\n\n.artifact-meta[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 16px;\n margin-bottom: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.meta-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.meta-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.meta-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.artifact-description[_ngcontent-%COMP%] {\n padding: 12px;\n margin-bottom: 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n border-radius: 4px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.json-viewer[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.btn-icon[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n padding: 6px 12px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: all 0.2s;\n}\n\n.btn-icon[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-icon.btn-primary[_ngcontent-%COMP%]:hover {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.btn-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.modal-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n}\n\n.modal-content[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n\n.modal-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.modal-body[_ngcontent-%COMP%] {\n padding: 20px;\n overflow-y: auto;\n}\n\n.modal-footer[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.form-section[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.form-section[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-select[_ngcontent-%COMP%], \n.form-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.2s;\n}\n\n.form-select[_ngcontent-%COMP%]:focus, \n.form-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.divider[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin: 24px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.divider[_ngcontent-%COMP%]::before, \n.divider[_ngcontent-%COMP%]::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.divider[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n padding: 0 12px;\n}\n\n.create-collection-row[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.create-collection-row[_ngcontent-%COMP%] .form-input[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n.btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n}\n\n.btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.btn-primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-primary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-secondary[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.btn-secondary[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n}\n\n\n\n.tab-navigation[_ngcontent-%COMP%] {\n display: flex;\n gap: 0;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 16px;\n background: var(--mj-bg-surface);\n}\n\n.tab-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 12px 20px;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.tab-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.tab-btn.active[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n\n\n.tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n width: 100%;\n box-sizing: border-box;\n margin-bottom: 5px;\n min-width: 0;\n min-height: 0;\n}\n\n\n\n.plugin-container[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.plugin-container.plugin-hidden[_ngcontent-%COMP%], \n.tab-hidden[_ngcontent-%COMP%] {\n display: none;\n}\n\n\n\n.plugin-container[_ngcontent-%COMP%] mj-artifact-type-plugin-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n}\n\n.display-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n min-height: 0;\n min-width: 0;\n padding: 7px;\n}\n\n.display-toolbar[_ngcontent-%COMP%] {\n position: absolute;\n top: 12px;\n right: 12px;\n display: flex;\n gap: 8px;\n z-index: 10;\n}\n\n.markdown-content[_ngcontent-%COMP%], \n.html-content[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 14px;\n line-height: 1.6;\n width: 100%;\n padding: 20px 10px 5px 20px; \n\n box-sizing: border-box;\n overflow: auto;\n min-height: 0;\n}\n\n.details-content[_ngcontent-%COMP%] {\n padding: 20px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.details-content[_ngcontent-%COMP%] .artifact-meta[_ngcontent-%COMP%] {\n margin-bottom: 0;\n padding: 20px;\n}\n\n.details-content[_ngcontent-%COMP%] .meta-item.full-width[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.attributes-section[_ngcontent-%COMP%] {\n margin-top: 24px;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.attributes-section[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.attributes-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 16px;\n}\n\n.attribute-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.attribute-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.attribute-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-word;\n}\n\n.attribute-empty-pill[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n font-size: 11px;\n font-weight: 500;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n\n\n.links-container[_ngcontent-%COMP%] {\n padding: 20px;\n}\n\n.links-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.link-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n transition: all 0.15s;\n}\n\n.link-item.clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.link-item.clickable[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n background: var(--mj-bg-surface-sunken);\n}\n\n.link-item.disabled[_ngcontent-%COMP%] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.link-item[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.link-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.link-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n color: var(--mj-brand-primary);\n}\n\n.link-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.link-name[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.link-type[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.link-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.link-actions[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n transition: all 0.15s;\n}\n\n.link-item.clickable[_ngcontent-%COMP%]:hover .link-actions[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n}\n\n.links-container[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-disabled);\n text-align: center;\n}\n\n.links-container[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.links-container[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.dynamic-tab-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n padding: 16px;\n}\n\n\n\n.component-tab-content[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: auto;\n padding: 16px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n line-height: 1.6;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] h1[_ngcontent-%COMP%], .markdown-viewer[_ngcontent-%COMP%] h2[_ngcontent-%COMP%], .markdown-viewer[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin-top: 24px;\n margin-bottom: 12px;\n font-weight: 600;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] h1[_ngcontent-%COMP%] { font-size: 24px; }\n.markdown-viewer[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] { font-size: 20px; }\n.markdown-viewer[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { font-size: 18px; }\n\n.markdown-viewer[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] ul[_ngcontent-%COMP%], .markdown-viewer[_ngcontent-%COMP%] ol[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n padding-left: 24px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 3px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n overflow-x: auto;\n margin-bottom: 12px;\n}\n\n.markdown-viewer[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: none;\n padding: 0;\n}\n\n.code-viewer[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.code-toolbar[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.code-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.plaintext-viewer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n font-family: 'Courier New', monospace;\n font-size: 13px;\n white-space: pre-wrap;\n}\n\n.html-viewer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n}\n\n\n\n@media (max-width: 768px) {\n \n\n .artifact-viewer-panel[_ngcontent-%COMP%] {\n border-top: 3px solid var(--mj-brand-primary);\n position: relative;\n }\n\n \n\n .artifact-viewer-panel[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n top: -8px;\n left: 0;\n right: 0;\n height: 8px;\n background: var(--mj-brand-secondary);\n }\n\n .tab-navigation[_ngcontent-%COMP%] {\n padding: 0 8px;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n }\n\n .tab-navigation[_ngcontent-%COMP%]::-webkit-scrollbar {\n display: none;\n }\n\n .tab-btn[_ngcontent-%COMP%] {\n padding: 10px 12px;\n font-size: 12px;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .panel-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .dynamic-tab-content[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .markdown-viewer[_ngcontent-%COMP%] {\n padding: 12px;\n }\n}\n\n\n\n@media (max-width: 480px) {\n .tab-navigation[_ngcontent-%COMP%] {\n padding: 0 4px;\n }\n\n .tab-btn[_ngcontent-%COMP%] {\n padding: 8px 10px;\n font-size: 11px;\n gap: 4px;\n }\n\n .tab-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .panel-header[_ngcontent-%COMP%] {\n padding: 8px;\n }\n\n .dynamic-tab-content[_ngcontent-%COMP%] {\n padding: 8px;\n }\n\n .markdown-viewer[_ngcontent-%COMP%] {\n padding: 8px;\n }\n}"] });
1536
1637
  }
1537
1638
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ArtifactViewerPanelComponent, [{
1538
1639
  type: Component,
1539
- args: [{ standalone: false, selector: 'mj-artifact-viewer-panel', template: "<div class=\"artifact-viewer-panel\" [class.no-header]=\"!showHeader\">\n @if (showHeader) {\n <div class=\"panel-header\">\n <div class=\"panel-header-left\">\n <h3>\n <i class=\"fas\" [ngClass]=\"getArtifactIcon()\"></i>\n {{ displayName }}\n </h3>\n @if (displayDescription) {\n <p class=\"header-description\">{{ displayDescription }}</p>\n }\n </div>\n <div class=\"panel-header-right\">\n <div class=\"version-selector\"\n [class.clickable]=\"allVersions.length > 1 && viewContext !== 'collection'\"\n (click)=\"viewContext !== 'collection' && toggleVersionDropdown()\">\n <i class=\"fas fa-history\"></i>\n <span class=\"version-label\">v{{ selectedVersionNumber }}</span>\n @if (allVersions.length > 1 && viewContext !== 'collection') {\n <i class=\"fas fa-chevron-down dropdown-icon\" [class.open]=\"showVersionDropdown\"></i>\n }\n @if (showVersionDropdown) {\n <div class=\"version-dropdown\" (click)=\"$event.stopPropagation()\">\n @for (version of allVersions; track version.ID) {\n <div class=\"version-option\"\n [class.selected]=\"version.VersionNumber === selectedVersionNumber\"\n (click)=\"selectVersion(version); $event.stopPropagation()\">\n <span class=\"version-number\">v{{ version.VersionNumber }}</span>\n <span class=\"version-date\">{{ version.__mj_CreatedAt | date:'short' }}</span>\n @if (version.VersionNumber === selectedVersionNumber) {\n <i class=\"fas fa-check\"></i>\n }\n </div>\n }\n </div>\n }\n </div>\n @if (showSaveToCollection) {\n <button class=\"save-to-collection-btn\"\n [class.in-collection]=\"isInCollection\"\n (click)=\"onSaveToLibrary()\"\n [title]=\"isInCollection ? 'Current version saved to ' + currentVersionCollections.length + ' collection(s)' : 'Save to Collection'\">\n <i [class]=\"isInCollection ? 'fas fa-bookmark' : 'far fa-bookmark'\"></i>\n </button>\n }\n @if (canShare) {\n <button class=\"share-btn\"\n (click)=\"onShare()\"\n title=\"Share\">\n <i class=\"fas fa-share-nodes\"></i>\n </button>\n }\n @if (showMaximizeButton) {\n <button class=\"maximize-btn\"\n (click)=\"onMaximizeToggle()\"\n [title]=\"isMaximized ? 'Restore Width' : 'Maximize Width'\">\n <i class=\"fas\" [ngClass]=\"isMaximized ? 'fa-compress-arrows-alt' : 'fa-arrows-left-right'\"></i>\n </button>\n }\n @if (showCloseButton) {\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n </div>\n }\n\n <div class=\"panel-content\">\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading artifact...</span>\n </div>\n }\n\n @if (error) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ error }}</span>\n </div>\n }\n\n @if (!isLoading && !error && artifact) {\n <div class=\"artifact-content-wrapper\" [class.no-tabs]=\"!showTabs\">\n <!-- Tab Navigation (Dynamic) - Hidden when showTabs is false -->\n @if (showTabs) {\n <div class=\"tab-navigation\">\n @for (tab of allTabs; track tab) {\n <button class=\"tab-btn\"\n [class.active]=\"activeTab === tab.toLowerCase()\"\n (click)=\"SetActiveTab(tab)\">\n @if (GetTabIcon(tab)) {\n <i [class]=\"GetTabIcon(tab)!\"></i>\n }\n {{ tab }}\n </button>\n }\n </div>\n }\n\n <!-- Tab Content (Dynamic) -->\n <div class=\"tab-content\">\n <!-- Plugin Viewer - Created once, kept alive, shown/hidden with CSS -->\n @if (hasPlugin && artifactVersion && artifactTypeName) {\n <div class=\"plugin-container\" [class.plugin-hidden]=\"activeTab !== 'display'\">\n <mj-artifact-type-plugin-viewer\n [artifactVersion]=\"artifactVersion\"\n [artifactTypeName]=\"artifactTypeName\"\n [contentType]=\"contentType\"\n [readonly]=\"true\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\"\n (navigationRequest)=\"onNavigationRequest($event)\"\n (pluginLoaded)=\"onPluginLoaded()\"\n (tabsChanged)=\"onTabsChanged()\">\n </mj-artifact-type-plugin-viewer>\n </div>\n }\n\n <!-- Display Tab - Fallback content when no plugin -->\n @if (activeTab === 'display' && (!hasPlugin || !artifactVersion)) {\n <div class=\"display-content\">\n @if (displayMarkdown || displayHtml) {\n <!-- Fallback to extracted markdown/HTML attributes -->\n <div class=\"display-toolbar\">\n <button class=\"btn-icon\" title=\"Print\" (click)=\"onPrintDisplayContent()\">\n <i class=\"fas fa-print\"></i> Print\n </button>\n <button class=\"btn-icon\" title=\"Copy Content\" (click)=\"onCopyDisplayContent()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n @if (displayMarkdown) {\n <div class=\"markdown-content\">\n <mj-markdown [data]=\"displayMarkdown\"\n [enableCollapsibleHeadings]=\"true\"\n [enableLineNumbers]=\"true\"\n [enableSmartypants]=\"true\"\n [enableHtml]=\"true\"></mj-markdown>\n </div>\n } @else if (displayHtml) {\n <div class=\"html-content\" [innerHTML]=\"displayHtml\"></div>\n }\n }\n </div>\n }\n\n <!-- Details Tab - Artifact metadata (always in DOM, hidden with CSS) -->\n <div class=\"details-content\" [class.tab-hidden]=\"activeTab !== 'details'\">\n <div class=\"artifact-meta\">\n <div class=\"meta-item\">\n <label>Type</label>\n <span>{{ artifact.Type }}</span>\n </div>\n <div class=\"meta-item\">\n <label>Version</label>\n <span>{{ artifactVersion?.VersionNumber || 1 }}</span>\n </div>\n <div class=\"meta-item\">\n <label>Created</label>\n <span>{{ artifact.__mj_CreatedAt | date:'short' }}</span>\n </div>\n <div class=\"meta-item\">\n <label>Updated</label>\n <span>{{ artifactVersion?.__mj_UpdatedAt | date:'short' }}</span>\n </div>\n @if (artifact.Description) {\n <div class=\"meta-item full-width\">\n <label>Artifact Description</label>\n <span>{{ artifact.Description }}</span>\n </div>\n }\n @if (artifactVersion?.Description && artifact.Description && artifactVersion?.Description !== artifact.Description) {\n <div class=\"meta-item full-width\">\n <label>Version Description</label>\n <span>{{ artifactVersion?.Description }}</span>\n </div>\n }\n </div>\n\n <!-- Version Attributes -->\n @if (filteredAttributes.length > 0) {\n <div class=\"attributes-section\">\n <h4>Version Attributes</h4>\n <div class=\"attributes-list\">\n @for (attr of filteredAttributes; track attr.ID) {\n <div class=\"attribute-item\">\n <label>{{ attr.Name }}</label>\n @if (attr.Value) {\n <span>{{ attr.Value }}</span>\n } @else {\n <span class=\"attribute-empty-pill\">Empty</span>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Links Tab - Conversations and Collections (always in DOM, hidden with CSS) -->\n <div class=\"links-container\" [class.tab-hidden]=\"activeTab !== 'links'\">\n @if (linksToShow.length > 0) {\n <div class=\"links-section\">\n @for (link of linksToShow; track link.id) {\n <div class=\"link-item\"\n [class.disabled]=\"!link.hasAccess\"\n [class.clickable]=\"link.hasAccess\"\n (click)=\"link.hasAccess ? onNavigateToLink(link) : null\"\n [title]=\"link.hasAccess ? 'Click to open' : 'No access'\">\n <div class=\"link-icon\">\n @if (link.type === 'conversation') {\n <i class=\"fas fa-comments\"></i>\n } @else {\n <i class=\"fas fa-folder\"></i>\n }\n </div>\n <div class=\"link-content\">\n <div class=\"link-name\">{{ link.name }}</div>\n <div class=\"link-type\">{{ link.type === 'conversation' ? 'Conversation' : 'Collection' }}</div>\n </div>\n <div class=\"link-actions\">\n <i class=\"fas fa-arrow-right\"></i>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fas fa-link\"></i>\n <p>No links available</p>\n </div>\n }\n </div>\n\n <!-- Dynamic Plugin Tabs and Base Tabs (JSON, etc.) -->\n @if (activeTab !== 'display' && activeTab !== 'details' && activeTab !== 'links') {\n <!-- Check if this is a component tab -->\n @if (GetComponentTabType(activeTab); as componentType) {\n <div class=\"component-tab-content\">\n <ng-container *ngComponentOutlet=\"componentType; inputs: GetComponentInputs(activeTab)\"></ng-container>\n </div>\n } @else {\n @if (GetTabContent(activeTab); as tabData) {\n <div class=\"dynamic-tab-content\">\n @switch (tabData.type) {\n @case ('markdown') {\n <div class=\"markdown-viewer\">\n <mj-markdown [data]=\"tabData.content\"\n [enableCollapsibleHeadings]=\"true\"\n [enableLineNumbers]=\"true\"\n [enableSmartypants]=\"true\"\n [enableHtml]=\"true\"></mj-markdown>\n </div>\n }\n @case ('json') {\n <div class=\"json-viewer\">\n <div class=\"json-toolbar\">\n <button class=\"btn-icon\" title=\"Copy JSON\" (click)=\"onCopyToClipboard()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"json-editor-container\">\n <mj-code-editor\n [value]=\"tabData.content\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n [lineWrapping]=\"true\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n }\n @case ('code') {\n <div class=\"code-viewer\">\n <div class=\"code-toolbar\">\n <button class=\"btn-icon\" title=\"Copy Code\" (click)=\"onCopyToClipboard()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"code-editor-container\">\n <mj-code-editor\n [value]=\"tabData.content\"\n [language]=\"tabData.language || 'typescript'\"\n [readonly]=\"true\"\n [lineWrapping]=\"true\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n }\n @case ('html') {\n <div class=\"html-viewer\" [innerHTML]=\"tabData.content\"></div>\n }\n @case ('plaintext') {\n <pre class=\"plaintext-viewer\">{{ tabData.content }}</pre>\n }\n }\n </div>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n</div>\n\n", styles: [".artifact-viewer-panel {\n width: 100%;\n height: 100%;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.panel-header-left {\n flex: 1;\n min-width: 0;\n margin-right: 16px;\n}\n\n.panel-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header h3 i {\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.header-description {\n margin: 4px 0 0 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: normal;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.version-selector {\n position: relative;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.version-selector.clickable {\n cursor: pointer;\n}\n\n.version-selector.clickable:hover {\n background: var(--mj-border-default);\n}\n\n.version-selector i {\n font-size: 11px;\n}\n\n.version-selector .dropdown-icon {\n margin-left: 2px;\n transition: transform 0.2s;\n}\n\n.version-selector .dropdown-icon.open {\n transform: rotate(180deg);\n}\n\n.version-label {\n font-family: monospace;\n}\n\n.version-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 200px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n z-index: 1000;\n overflow: hidden;\n}\n\n.version-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n cursor: pointer;\n transition: background 0.15s;\n font-size: 13px;\n}\n\n.version-option:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.version-option.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.version-option .version-number {\n font-family: monospace;\n font-weight: 600;\n min-width: 35px;\n}\n\n.version-option .version-date {\n flex: 1;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.version-option i.fa-check {\n color: var(--mj-status-success);\n margin-left: auto;\n}\n\n.save-to-collection-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.save-to-collection-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.save-to-collection-btn i {\n font-size: 14px;\n}\n\n.save-to-collection-btn.in-collection {\n color: var(--mj-brand-primary);\n}\n\n.save-to-collection-btn.in-collection:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.share-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.share-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.share-btn i {\n font-size: 14px;\n}\n\n.maximize-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.maximize-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.maximize-btn i {\n font-size: 14px;\n}\n\n.close-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.close-btn i {\n font-size: 14px;\n}\n\n.panel-content {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n.artifact-content-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.loading-state,\n.error-state {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.error-state {\n color: var(--mj-status-error);\n}\n\n.loading-state i {\n font-size: 24px;\n}\n\n.artifact-meta {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 16px;\n margin-bottom: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.meta-item label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.meta-item span {\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.artifact-description {\n padding: 12px;\n margin-bottom: 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n border-radius: 4px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.json-viewer {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-editor-container {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-toolbar {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.btn-icon {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n padding: 6px 12px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: all 0.2s;\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon.btn-primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-icon.btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.btn-icon i {\n font-size: 14px;\n}\n\n/* Library Dialog Styles */\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n}\n\n.modal-content {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.modal-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-header h3 i {\n color: var(--mj-status-warning);\n}\n\n.modal-body {\n padding: 20px;\n overflow-y: auto;\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.form-section {\n margin-bottom: 20px;\n}\n\n.form-section label {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-select,\n.form-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.2s;\n}\n\n.form-select:focus,\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.divider {\n display: flex;\n align-items: center;\n margin: 24px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.divider::before,\n.divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.divider span {\n padding: 0 12px;\n}\n\n.create-collection-row {\n display: flex;\n gap: 8px;\n}\n\n.create-collection-row .form-input {\n flex: 1;\n}\n\n.btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n}\n\n.btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-secondary {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n}\n\n/* Tab Navigation */\n.tab-navigation {\n display: flex;\n gap: 0;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 16px;\n background: var(--mj-bg-surface);\n}\n\n.tab-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 12px 20px;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.tab-btn:hover {\n color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.tab-btn.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.tab-btn i {\n font-size: 14px;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow: auto;\n width: 100%;\n box-sizing: border-box;\n margin-bottom: 5px;\n min-width: 0;\n min-height: 0;\n}\n\n/* Plugin Container */\n.plugin-container {\n width: 100%;\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.plugin-container.plugin-hidden,\n.tab-hidden {\n display: none;\n}\n\n/* Ensure artifact viewer component takes full height */\n.plugin-container mj-artifact-type-plugin-viewer {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n}\n\n.display-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n min-height: 0;\n min-width: 0;\n padding: 7px;\n}\n\n.display-toolbar {\n position: absolute;\n top: 12px;\n right: 12px;\n display: flex;\n gap: 8px;\n z-index: 10;\n}\n\n.markdown-content,\n.html-content {\n flex: 1;\n font-size: 14px;\n line-height: 1.6;\n width: 100%;\n padding: 20px 10px 5px 20px; /* top right bottom left */\n box-sizing: border-box;\n overflow: auto;\n min-height: 0;\n}\n\n.details-content {\n padding: 20px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.details-content .artifact-meta {\n margin-bottom: 0;\n padding: 20px;\n}\n\n.details-content .meta-item.full-width {\n grid-column: 1 / -1;\n}\n\n.attributes-section {\n margin-top: 24px;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.attributes-section h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.attributes-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 16px;\n}\n\n.attribute-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.attribute-item label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.attribute-item span {\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-word;\n}\n\n.attribute-empty-pill {\n display: inline-block;\n padding: 2px 8px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n font-size: 11px;\n font-weight: 500;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Links Tab */\n.links-container {\n padding: 20px;\n}\n\n.links-section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.link-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n transition: all 0.15s;\n}\n\n.link-item.clickable {\n cursor: pointer;\n}\n\n.link-item.clickable:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n background: var(--mj-bg-surface-sunken);\n}\n\n.link-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.link-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.link-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.link-icon i {\n font-size: 18px;\n color: var(--mj-brand-primary);\n}\n\n.link-content {\n flex: 1;\n min-width: 0;\n}\n\n.link-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.link-type {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.link-actions {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.link-actions i {\n font-size: 14px;\n color: var(--mj-text-muted);\n transition: all 0.15s;\n}\n\n.link-item.clickable:hover .link-actions i {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n}\n\n.links-container .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-disabled);\n text-align: center;\n}\n\n.links-container .empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.links-container .empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* Dynamic Tab Content Styles */\n.dynamic-tab-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n padding: 16px;\n}\n\n/* Custom component tab content */\n.component-tab-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: auto;\n padding: 16px;\n}\n\n.markdown-viewer {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n line-height: 1.6;\n}\n\n.markdown-viewer h1, .markdown-viewer h2, .markdown-viewer h3 {\n margin-top: 24px;\n margin-bottom: 12px;\n font-weight: 600;\n}\n\n.markdown-viewer h1 { font-size: 24px; }\n.markdown-viewer h2 { font-size: 20px; }\n.markdown-viewer h3 { font-size: 18px; }\n\n.markdown-viewer p {\n margin-bottom: 12px;\n}\n\n.markdown-viewer ul, .markdown-viewer ol {\n margin-bottom: 12px;\n padding-left: 24px;\n}\n\n.markdown-viewer code {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 3px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n}\n\n.markdown-viewer pre {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n overflow-x: auto;\n margin-bottom: 12px;\n}\n\n.markdown-viewer pre code {\n background: none;\n padding: 0;\n}\n\n.code-viewer {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.code-toolbar {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.code-editor-container {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.plaintext-viewer {\n flex: 1;\n overflow: auto;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n font-family: 'Courier New', monospace;\n font-size: 13px;\n white-space: pre-wrap;\n}\n\n.html-viewer {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n}\n\n/* Mobile adjustments: 481px - 768px */\n@media (max-width: 768px) {\n /* Add top border with slight visual separation from top nav */\n .artifact-viewer-panel {\n border-top: 3px solid var(--mj-brand-primary);\n position: relative;\n }\n\n /* Create a small dark strip above the blue border to separate from top nav */\n .artifact-viewer-panel::before {\n content: '';\n position: absolute;\n top: -8px;\n left: 0;\n right: 0;\n height: 8px;\n background: var(--mj-brand-secondary);\n }\n\n .tab-navigation {\n padding: 0 8px;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n }\n\n .tab-navigation::-webkit-scrollbar {\n display: none;\n }\n\n .tab-btn {\n padding: 10px 12px;\n font-size: 12px;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .tab-btn i {\n font-size: 13px;\n }\n\n .panel-header {\n padding: 12px;\n }\n\n .dynamic-tab-content {\n padding: 12px;\n }\n\n .markdown-viewer {\n padding: 12px;\n }\n}\n\n/* Small Phone adjustments: <= 480px */\n@media (max-width: 480px) {\n .tab-navigation {\n padding: 0 4px;\n }\n\n .tab-btn {\n padding: 8px 10px;\n font-size: 11px;\n gap: 4px;\n }\n\n .tab-btn i {\n font-size: 12px;\n }\n\n .panel-header {\n padding: 8px;\n }\n\n .dynamic-tab-content {\n padding: 8px;\n }\n\n .markdown-viewer {\n padding: 8px;\n }\n}\n"] }]
1640
+ args: [{ standalone: false, selector: 'mj-artifact-viewer-panel', template: "<div class=\"artifact-viewer-panel\" [class.no-header]=\"!showHeader\">\n @if (showHeader) {\n <div class=\"panel-header\">\n <div class=\"panel-header-left\">\n <h3>\n <i class=\"fas\" [ngClass]=\"artifactIcon\"></i>\n {{ displayName }}\n </h3>\n @if (displayDescription) {\n <p class=\"header-description\">{{ displayDescription }}</p>\n }\n </div>\n <div class=\"panel-header-right\">\n <div class=\"version-selector\"\n [class.clickable]=\"allVersions.length > 1 && viewContext !== 'collection'\"\n (click)=\"viewContext !== 'collection' && toggleVersionDropdown()\">\n <i class=\"fas fa-history\"></i>\n <span class=\"version-label\">v{{ selectedVersionNumber }}</span>\n @if (allVersions.length > 1 && viewContext !== 'collection') {\n <i class=\"fas fa-chevron-down dropdown-icon\" [class.open]=\"showVersionDropdown\"></i>\n }\n @if (showVersionDropdown) {\n <div class=\"version-dropdown\" (click)=\"$event.stopPropagation()\">\n @for (version of allVersions; track version.ID) {\n <div class=\"version-option\"\n [class.selected]=\"version.VersionNumber === selectedVersionNumber\"\n (click)=\"selectVersion(version); $event.stopPropagation()\">\n <span class=\"version-number\">v{{ version.VersionNumber }}</span>\n <span class=\"version-date\">{{ version.__mj_CreatedAt | date:'short' }}</span>\n @if (version.VersionNumber === selectedVersionNumber) {\n <i class=\"fas fa-check\"></i>\n }\n </div>\n }\n </div>\n }\n </div>\n @if (pluginViewer?.SupportsFeedback) {\n <button class=\"feedback-btn\"\n (click)=\"pluginViewer?.AskUserForFeedback()\"\n title=\"Inspect & rate components\">\n <i class=\"fas fa-star-half-stroke\"></i>\n </button>\n }\n @if (showSaveToCollection) {\n <button class=\"save-to-collection-btn\"\n [class.in-collection]=\"isInCollection\"\n (click)=\"onSaveToLibrary()\"\n [title]=\"isInCollection ? 'Current version saved to ' + currentVersionCollections.length + ' collection(s)' : 'Save to Collection'\">\n <i [class]=\"isInCollection ? 'fas fa-bookmark' : 'far fa-bookmark'\"></i>\n </button>\n }\n @if (canShare) {\n <button class=\"share-btn\"\n (click)=\"onShare()\"\n title=\"Share\">\n <i class=\"fas fa-share-nodes\"></i>\n </button>\n }\n @if (showMaximizeButton) {\n <button class=\"maximize-btn\"\n (click)=\"onMaximizeToggle()\"\n [title]=\"isMaximized ? 'Restore Width' : 'Maximize Width'\">\n <i class=\"fas\" [ngClass]=\"isMaximized ? 'fa-compress-arrows-alt' : 'fa-arrows-left-right'\"></i>\n </button>\n }\n @if (showCloseButton) {\n <button class=\"close-btn\" (click)=\"onClose()\" title=\"Close\">\n <i class=\"fas fa-times\"></i>\n </button>\n }\n </div>\n </div>\n }\n\n <div class=\"panel-content\">\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin\"></i>\n <span>Loading artifact...</span>\n </div>\n }\n\n @if (error) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle\"></i>\n <span>{{ error }}</span>\n </div>\n }\n\n @if (!isLoading && !error && artifact) {\n <div class=\"artifact-content-wrapper\" [class.no-tabs]=\"!showTabs\">\n <!-- Tab Navigation (Dynamic) - Hidden when showTabs is false -->\n @if (showTabs) {\n <div class=\"tab-navigation\">\n @for (tab of allTabs; track tab) {\n <button class=\"tab-btn\"\n [class.active]=\"activeTab === tab.toLowerCase()\"\n (click)=\"SetActiveTab(tab)\">\n @if (GetTabIcon(tab)) {\n <i [class]=\"GetTabIcon(tab)!\"></i>\n }\n {{ tab }}\n </button>\n }\n </div>\n }\n\n <!-- Tab Content (Dynamic) -->\n <div class=\"tab-content\">\n <!-- Plugin Viewer - Created once, kept alive, shown/hidden with CSS -->\n @if (hasPlugin && artifactVersion && artifactTypeName) {\n <div class=\"plugin-container\" [class.plugin-hidden]=\"activeTab !== 'display'\">\n <mj-artifact-type-plugin-viewer\n [artifactVersion]=\"artifactVersion\"\n [artifactTypeName]=\"artifactTypeName\"\n [contentType]=\"contentType\"\n [readonly]=\"true\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\"\n (navigationRequest)=\"onNavigationRequest($event)\"\n (pluginLoaded)=\"onPluginLoaded()\"\n (tabsChanged)=\"onTabsChanged()\">\n </mj-artifact-type-plugin-viewer>\n </div>\n }\n\n <!-- Display Tab - Fallback content when no plugin -->\n @if (activeTab === 'display' && (!hasPlugin || !artifactVersion)) {\n <div class=\"display-content\">\n @if (displayMarkdown || displayHtml) {\n <!-- Fallback to extracted markdown/HTML attributes -->\n <div class=\"display-toolbar\">\n <button class=\"btn-icon\" title=\"Print\" (click)=\"onPrintDisplayContent()\">\n <i class=\"fas fa-print\"></i> Print\n </button>\n <button class=\"btn-icon\" title=\"Copy Content\" (click)=\"onCopyDisplayContent()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n @if (displayMarkdown) {\n <div class=\"markdown-content\">\n <mj-markdown [data]=\"displayMarkdown\"\n [enableCollapsibleHeadings]=\"true\"\n [enableLineNumbers]=\"true\"\n [enableSmartypants]=\"true\"\n [enableHtml]=\"true\"></mj-markdown>\n </div>\n } @else if (displayHtml) {\n <div class=\"html-content\" [innerHTML]=\"displayHtml\"></div>\n }\n }\n </div>\n }\n\n <!-- Details Tab - Artifact metadata (always in DOM, hidden with CSS) -->\n <div class=\"details-content\" [class.tab-hidden]=\"activeTab !== 'details'\">\n <div class=\"artifact-meta\">\n <div class=\"meta-item\">\n <label>Type</label>\n <span>{{ artifact.Type }}</span>\n </div>\n <div class=\"meta-item\">\n <label>Version</label>\n <span>{{ artifactVersion?.VersionNumber || 1 }}</span>\n </div>\n <div class=\"meta-item\">\n <label>Created</label>\n <span>{{ artifact.__mj_CreatedAt | date:'short' }}</span>\n </div>\n <div class=\"meta-item\">\n <label>Updated</label>\n <span>{{ artifactVersion?.__mj_UpdatedAt | date:'short' }}</span>\n </div>\n @if (artifact.Description) {\n <div class=\"meta-item full-width\">\n <label>Artifact Description</label>\n <span>{{ artifact.Description }}</span>\n </div>\n }\n @if (artifactVersion?.Description && artifact.Description && artifactVersion?.Description !== artifact.Description) {\n <div class=\"meta-item full-width\">\n <label>Version Description</label>\n <span>{{ artifactVersion?.Description }}</span>\n </div>\n }\n </div>\n\n <!-- Version Attributes -->\n @if (filteredAttributes.length > 0) {\n <div class=\"attributes-section\">\n <h4>Version Attributes</h4>\n <div class=\"attributes-list\">\n @for (attr of filteredAttributes; track attr.ID) {\n <div class=\"attribute-item\">\n <label>{{ attr.Name }}</label>\n @if (attr.Value) {\n <span>{{ attr.Value }}</span>\n } @else {\n <span class=\"attribute-empty-pill\">Empty</span>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Links Tab - Conversations and Collections (always in DOM, hidden with CSS) -->\n <div class=\"links-container\" [class.tab-hidden]=\"activeTab !== 'links'\">\n @if (linksToShow.length > 0) {\n <div class=\"links-section\">\n @for (link of linksToShow; track link.id) {\n <div class=\"link-item\"\n [class.disabled]=\"!link.hasAccess\"\n [class.clickable]=\"link.hasAccess\"\n (click)=\"link.hasAccess ? onNavigateToLink(link) : null\"\n [title]=\"link.hasAccess ? 'Click to open' : 'No access'\">\n <div class=\"link-icon\">\n @if (link.type === 'conversation') {\n <i class=\"fas fa-comments\"></i>\n } @else {\n <i class=\"fas fa-folder\"></i>\n }\n </div>\n <div class=\"link-content\">\n <div class=\"link-name\">{{ link.name }}</div>\n <div class=\"link-type\">{{ link.type === 'conversation' ? 'Conversation' : 'Collection' }}</div>\n </div>\n <div class=\"link-actions\">\n <i class=\"fas fa-arrow-right\"></i>\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fas fa-link\"></i>\n <p>No links available</p>\n </div>\n }\n </div>\n\n <!-- Dynamic Plugin Tabs and Base Tabs (JSON, etc.) -->\n @if (activeTab !== 'display' && activeTab !== 'details' && activeTab !== 'links') {\n <!-- Check if this is a component tab -->\n @if (GetComponentTabType(activeTab); as componentType) {\n <div class=\"component-tab-content\">\n <ng-container *ngComponentOutlet=\"componentType; inputs: GetComponentInputs(activeTab)\"></ng-container>\n </div>\n } @else {\n @if (GetTabContent(activeTab); as tabData) {\n <div class=\"dynamic-tab-content\">\n @switch (tabData.type) {\n @case ('markdown') {\n <div class=\"markdown-viewer\">\n <mj-markdown [data]=\"tabData.content\"\n [enableCollapsibleHeadings]=\"true\"\n [enableLineNumbers]=\"true\"\n [enableSmartypants]=\"true\"\n [enableHtml]=\"true\"></mj-markdown>\n </div>\n }\n @case ('json') {\n <div class=\"json-viewer\">\n <div class=\"json-toolbar\">\n <button class=\"btn-icon\" title=\"Copy JSON\" (click)=\"onCopyToClipboard()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"json-editor-container\">\n <mj-code-editor\n [value]=\"tabData.content\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n [lineWrapping]=\"true\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n }\n @case ('code') {\n <div class=\"code-viewer\">\n <div class=\"code-toolbar\">\n <button class=\"btn-icon\" title=\"Copy Code\" (click)=\"onCopyToClipboard()\">\n <i class=\"fas fa-copy\"></i> Copy\n </button>\n </div>\n <div class=\"code-editor-container\">\n <mj-code-editor\n [value]=\"tabData.content\"\n [language]=\"tabData.language || 'typescript'\"\n [readonly]=\"true\"\n [lineWrapping]=\"true\"\n style=\"width: 100%; height: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n }\n @case ('html') {\n <div class=\"html-viewer\" [innerHTML]=\"tabData.content\"></div>\n }\n @case ('plaintext') {\n <pre class=\"plaintext-viewer\">{{ tabData.content }}</pre>\n }\n }\n </div>\n }\n }\n }\n </div>\n </div>\n }\n </div>\n</div>\n\n", styles: [".artifact-viewer-panel {\n width: 100%;\n height: 100%;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 12px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.panel-header-left {\n flex: 1;\n min-width: 0;\n margin-right: 16px;\n}\n\n.panel-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header h3 i {\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.header-description {\n margin: 4px 0 0 0;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: normal;\n word-wrap: break-word;\n overflow-wrap: break-word;\n}\n\n.panel-header-right {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.version-selector {\n position: relative;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 12px;\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: 500;\n transition: all 0.2s;\n}\n\n.version-selector.clickable {\n cursor: pointer;\n}\n\n.version-selector.clickable:hover {\n background: var(--mj-border-default);\n}\n\n.version-selector i {\n font-size: 11px;\n}\n\n.version-selector .dropdown-icon {\n margin-left: 2px;\n transition: transform 0.2s;\n}\n\n.version-selector .dropdown-icon.open {\n transform: rotate(180deg);\n}\n\n.version-label {\n font-family: monospace;\n}\n\n.version-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 200px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-md);\n z-index: 1000;\n overflow: hidden;\n}\n\n.version-option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n cursor: pointer;\n transition: background 0.15s;\n font-size: 13px;\n}\n\n.version-option:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.version-option.selected {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.version-option .version-number {\n font-family: monospace;\n font-weight: 600;\n min-width: 35px;\n}\n\n.version-option .version-date {\n flex: 1;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.version-option i.fa-check {\n color: var(--mj-status-success);\n margin-left: auto;\n}\n\n.feedback-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.feedback-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.feedback-btn i {\n font-size: 14px;\n}\n\n.save-to-collection-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.save-to-collection-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n}\n\n.save-to-collection-btn i {\n font-size: 14px;\n}\n\n.save-to-collection-btn.in-collection {\n color: var(--mj-brand-primary);\n}\n\n.save-to-collection-btn.in-collection:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.share-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.share-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-brand-primary);\n}\n\n.share-btn i {\n font-size: 14px;\n}\n\n.maximize-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.maximize-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.maximize-btn i {\n font-size: 14px;\n}\n\n.close-btn {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 6px;\n border-radius: 4px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n}\n\n.close-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.close-btn i {\n font-size: 14px;\n}\n\n.panel-content {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n.artifact-content-wrapper {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-height: 0;\n width: 100%;\n box-sizing: border-box;\n}\n\n.loading-state,\n.error-state {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-muted);\n}\n\n.error-state {\n color: var(--mj-status-error);\n}\n\n.loading-state i {\n font-size: 24px;\n}\n\n.artifact-meta {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 16px;\n margin-bottom: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.meta-item label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.meta-item span {\n font-size: 14px;\n color: var(--mj-text-primary);\n}\n\n.artifact-description {\n padding: 12px;\n margin-bottom: 16px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-left: 3px solid var(--mj-brand-primary);\n border-radius: 4px;\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n}\n\n.json-viewer {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-editor-container {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.json-toolbar {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.btn-icon {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n border-radius: 4px;\n padding: 6px 12px;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: all 0.2s;\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-text-disabled);\n}\n\n.btn-icon.btn-primary {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-icon.btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n border-color: var(--mj-brand-primary-hover);\n}\n\n.btn-icon i {\n font-size: 14px;\n}\n\n/* Library Dialog Styles */\n.modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n}\n\n.modal-content {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n max-width: 500px;\n width: 90%;\n max-height: 90vh;\n display: flex;\n flex-direction: column;\n}\n\n.modal-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.modal-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.modal-header h3 i {\n color: var(--mj-status-warning);\n}\n\n.modal-body {\n padding: 20px;\n overflow-y: auto;\n}\n\n.modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.form-section {\n margin-bottom: 20px;\n}\n\n.form-section label {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.form-select,\n.form-input {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--mj-border-strong);\n border-radius: 6px;\n font-size: 14px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n transition: border-color 0.2s;\n}\n\n.form-select:focus,\n.form-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.divider {\n display: flex;\n align-items: center;\n margin: 24px 0;\n color: var(--mj-text-disabled);\n font-size: 12px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.divider::before,\n.divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--mj-border-default);\n}\n\n.divider span {\n padding: 0 12px;\n}\n\n.create-collection-row {\n display: flex;\n gap: 8px;\n}\n\n.create-collection-row .form-input {\n flex: 1;\n}\n\n.btn {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n}\n\n.btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.btn-secondary {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n}\n\n/* Tab Navigation */\n.tab-navigation {\n display: flex;\n gap: 0;\n border-bottom: 2px solid var(--mj-border-default);\n padding: 0 16px;\n background: var(--mj-bg-surface);\n}\n\n.tab-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 12px 20px;\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n margin-bottom: -2px;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.tab-btn:hover {\n color: var(--mj-brand-primary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.tab-btn.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.tab-btn i {\n font-size: 14px;\n}\n\n/* Tab Content */\n.tab-content {\n flex: 1;\n overflow: auto;\n width: 100%;\n box-sizing: border-box;\n margin-bottom: 5px;\n min-width: 0;\n min-height: 0;\n}\n\n/* Plugin Container */\n.plugin-container {\n width: 100%;\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.plugin-container.plugin-hidden,\n.tab-hidden {\n display: none;\n}\n\n/* Ensure artifact viewer component takes full height */\n.plugin-container mj-artifact-type-plugin-viewer {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n width: 100%;\n}\n\n.display-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n box-sizing: border-box;\n overflow: hidden;\n min-height: 0;\n min-width: 0;\n padding: 7px;\n}\n\n.display-toolbar {\n position: absolute;\n top: 12px;\n right: 12px;\n display: flex;\n gap: 8px;\n z-index: 10;\n}\n\n.markdown-content,\n.html-content {\n flex: 1;\n font-size: 14px;\n line-height: 1.6;\n width: 100%;\n padding: 20px 10px 5px 20px; /* top right bottom left */\n box-sizing: border-box;\n overflow: auto;\n min-height: 0;\n}\n\n.details-content {\n padding: 20px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.details-content .artifact-meta {\n margin-bottom: 0;\n padding: 20px;\n}\n\n.details-content .meta-item.full-width {\n grid-column: 1 / -1;\n}\n\n.attributes-section {\n margin-top: 24px;\n padding: 24px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.attributes-section h4 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.attributes-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 16px;\n}\n\n.attribute-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 12px;\n background: var(--mj-bg-surface);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.attribute-item label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.attribute-item span {\n font-size: 13px;\n color: var(--mj-text-primary);\n word-break: break-word;\n}\n\n.attribute-empty-pill {\n display: inline-block;\n padding: 2px 8px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n font-size: 11px;\n font-weight: 500;\n border-radius: 4px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Links Tab */\n.links-container {\n padding: 20px;\n}\n\n.links-section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.link-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n transition: all 0.15s;\n}\n\n.link-item.clickable {\n cursor: pointer;\n}\n\n.link-item.clickable:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n background: var(--mj-bg-surface-sunken);\n}\n\n.link-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.link-item:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.link-icon {\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n flex-shrink: 0;\n}\n\n.link-icon i {\n font-size: 18px;\n color: var(--mj-brand-primary);\n}\n\n.link-content {\n flex: 1;\n min-width: 0;\n}\n\n.link-name {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.link-type {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n}\n\n.link-actions {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n flex-shrink: 0;\n}\n\n.link-actions i {\n font-size: 14px;\n color: var(--mj-text-muted);\n transition: all 0.15s;\n}\n\n.link-item.clickable:hover .link-actions i {\n color: var(--mj-brand-primary);\n transform: translateX(2px);\n}\n\n.links-container .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n color: var(--mj-text-disabled);\n text-align: center;\n}\n\n.links-container .empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.3;\n}\n\n.links-container .empty-state p {\n margin: 0;\n font-size: 14px;\n}\n\n/* Dynamic Tab Content Styles */\n.dynamic-tab-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n padding: 16px;\n}\n\n/* Custom component tab content */\n.component-tab-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: auto;\n padding: 16px;\n}\n\n.markdown-viewer {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n line-height: 1.6;\n}\n\n.markdown-viewer h1, .markdown-viewer h2, .markdown-viewer h3 {\n margin-top: 24px;\n margin-bottom: 12px;\n font-weight: 600;\n}\n\n.markdown-viewer h1 { font-size: 24px; }\n.markdown-viewer h2 { font-size: 20px; }\n.markdown-viewer h3 { font-size: 18px; }\n\n.markdown-viewer p {\n margin-bottom: 12px;\n}\n\n.markdown-viewer ul, .markdown-viewer ol {\n margin-bottom: 12px;\n padding-left: 24px;\n}\n\n.markdown-viewer code {\n background: var(--mj-bg-surface-sunken);\n padding: 2px 6px;\n border-radius: 3px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n}\n\n.markdown-viewer pre {\n background: var(--mj-bg-surface-sunken);\n padding: 12px;\n border-radius: 6px;\n overflow-x: auto;\n margin-bottom: 12px;\n}\n\n.markdown-viewer pre code {\n background: none;\n padding: 0;\n}\n\n.code-viewer {\n flex: 1;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n min-height: 0;\n}\n\n.code-toolbar {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.code-editor-container {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n}\n\n.plaintext-viewer {\n flex: 1;\n overflow: auto;\n padding: 12px;\n background: var(--mj-bg-surface-sunken);\n font-family: 'Courier New', monospace;\n font-size: 13px;\n white-space: pre-wrap;\n}\n\n.html-viewer {\n flex: 1;\n overflow: auto;\n padding: 20px;\n background: var(--mj-bg-surface);\n}\n\n/* Mobile adjustments: 481px - 768px */\n@media (max-width: 768px) {\n /* Add top border with slight visual separation from top nav */\n .artifact-viewer-panel {\n border-top: 3px solid var(--mj-brand-primary);\n position: relative;\n }\n\n /* Create a small dark strip above the blue border to separate from top nav */\n .artifact-viewer-panel::before {\n content: '';\n position: absolute;\n top: -8px;\n left: 0;\n right: 0;\n height: 8px;\n background: var(--mj-brand-secondary);\n }\n\n .tab-navigation {\n padding: 0 8px;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n }\n\n .tab-navigation::-webkit-scrollbar {\n display: none;\n }\n\n .tab-btn {\n padding: 10px 12px;\n font-size: 12px;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .tab-btn i {\n font-size: 13px;\n }\n\n .panel-header {\n padding: 12px;\n }\n\n .dynamic-tab-content {\n padding: 12px;\n }\n\n .markdown-viewer {\n padding: 12px;\n }\n}\n\n/* Small Phone adjustments: <= 480px */\n@media (max-width: 480px) {\n .tab-navigation {\n padding: 0 4px;\n }\n\n .tab-btn {\n padding: 8px 10px;\n font-size: 11px;\n gap: 4px;\n }\n\n .tab-btn i {\n font-size: 12px;\n }\n\n .panel-header {\n padding: 8px;\n }\n\n .dynamic-tab-content {\n padding: 8px;\n }\n\n .markdown-viewer {\n padding: 8px;\n }\n}\n"] }]
1540
1641
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.MJNotificationService }, { type: i2.DomSanitizer }, { type: i3.ArtifactIconService }], { artifactId: [{
1541
1642
  type: Input
1542
1643
  }], currentUser: [{