@memberjunction/ng-artifacts 5.42.0 → 5.44.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 (64) hide show
  1. package/README.md +6 -0
  2. package/dist/lib/artifacts.module.d.ts +28 -25
  3. package/dist/lib/artifacts.module.d.ts.map +1 -1
  4. package/dist/lib/artifacts.module.js +22 -2
  5. package/dist/lib/artifacts.module.js.map +1 -1
  6. package/dist/lib/components/artifact-version-history.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact-version-history.component.js +26 -29
  8. package/dist/lib/components/artifact-version-history.component.js.map +1 -1
  9. package/dist/lib/components/artifact-viewer-panel.component.d.ts +3 -0
  10. package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
  11. package/dist/lib/components/artifact-viewer-panel.component.js +198 -112
  12. package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
  13. package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts +11 -0
  14. package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts.map +1 -1
  15. package/dist/lib/components/plugins/audio-artifact-viewer.component.js +37 -12
  16. package/dist/lib/components/plugins/audio-artifact-viewer.component.js.map +1 -1
  17. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts.map +1 -1
  18. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +40 -51
  19. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -1
  20. package/dist/lib/components/plugins/data-artifact-viewer.component.js +27 -47
  21. package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
  22. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js +89 -95
  23. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js.map +1 -1
  24. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts +227 -0
  25. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts.map +1 -0
  26. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js +630 -0
  27. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js.map +1 -0
  28. package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts +11 -0
  29. package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts.map +1 -1
  30. package/dist/lib/components/plugins/video-artifact-viewer.component.js +37 -12
  31. package/dist/lib/components/plugins/video-artifact-viewer.component.js.map +1 -1
  32. package/dist/lib/components/previews/audio-artifact-preview.component.d.ts +18 -4
  33. package/dist/lib/components/previews/audio-artifact-preview.component.d.ts.map +1 -1
  34. package/dist/lib/components/previews/audio-artifact-preview.component.js +54 -21
  35. package/dist/lib/components/previews/audio-artifact-preview.component.js.map +1 -1
  36. package/dist/lib/components/previews/video-artifact-preview.component.d.ts +19 -5
  37. package/dist/lib/components/previews/video-artifact-preview.component.d.ts.map +1 -1
  38. package/dist/lib/components/previews/video-artifact-preview.component.js +54 -22
  39. package/dist/lib/components/previews/video-artifact-preview.component.js.map +1 -1
  40. package/dist/public-api.d.ts +1 -0
  41. package/dist/public-api.d.ts.map +1 -1
  42. package/dist/public-api.js +1 -0
  43. package/dist/public-api.js.map +1 -1
  44. package/package.json +21 -18
  45. package/dist/__tests__/exports.test.d.ts +0 -2
  46. package/dist/__tests__/exports.test.d.ts.map +0 -1
  47. package/dist/__tests__/exports.test.js +0 -17
  48. package/dist/__tests__/exports.test.js.map +0 -1
  49. package/dist/__tests__/image-artifact-viewer.test.d.ts +0 -2
  50. package/dist/__tests__/image-artifact-viewer.test.d.ts.map +0 -1
  51. package/dist/__tests__/image-artifact-viewer.test.js +0 -62
  52. package/dist/__tests__/image-artifact-viewer.test.js.map +0 -1
  53. package/dist/__tests__/index.test.d.ts +0 -2
  54. package/dist/__tests__/index.test.d.ts.map +0 -1
  55. package/dist/__tests__/index.test.js +0 -7
  56. package/dist/__tests__/index.test.js.map +0 -1
  57. package/dist/lib/__tests__/artifact-snapshots.test.d.ts +0 -2
  58. package/dist/lib/__tests__/artifact-snapshots.test.d.ts.map +0 -1
  59. package/dist/lib/__tests__/artifact-snapshots.test.js +0 -155
  60. package/dist/lib/__tests__/artifact-snapshots.test.js.map +0 -1
  61. package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts +0 -2
  62. package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts.map +0 -1
  63. package/dist/lib/__tests__/interactive-form-apply.service.test.js +0 -211
  64. package/dist/lib/__tests__/interactive-form-apply.service.test.js.map +0 -1
@@ -0,0 +1,630 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Component, ChangeDetectorRef, Output, EventEmitter, inject } from '@angular/core';
8
+ import { RegisterClass } from '@memberjunction/global';
9
+ import { BaseArtifactViewerPluginComponent } from '../base-artifact-viewer.component';
10
+ import { createMarkdownSnapshot } from '../../snapshot-helpers';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/common";
13
+ import * as i2 from "@memberjunction/ng-shared-generic";
14
+ import * as i3 from "@memberjunction/ng-ui-components";
15
+ const _forTrack0 = ($index, $item) => $item.rank;
16
+ const _forTrack1 = ($index, $item) => $item.feature;
17
+ const _forTrack2 = ($index, $item) => $item.label;
18
+ function MLExperimentResultsViewerComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelementStart(0, "div", 1);
20
+ i0.ɵɵelement(1, "mj-loading", 3);
21
+ i0.ɵɵelementEnd();
22
+ } }
23
+ function MLExperimentResultsViewerComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
24
+ i0.ɵɵelementStart(0, "div", 2);
25
+ i0.ɵɵelement(1, "i", 4);
26
+ i0.ɵɵelementStart(2, "h3");
27
+ i0.ɵɵtext(3, "No experiment results to display");
28
+ i0.ɵɵelementEnd();
29
+ i0.ɵɵelementStart(4, "p");
30
+ i0.ɵɵtext(5);
31
+ i0.ɵɵelementEnd()();
32
+ } if (rf & 2) {
33
+ const ctx_r0 = i0.ɵɵnextContext();
34
+ i0.ɵɵadvance(5);
35
+ i0.ɵɵtextInterpolate(ctx_r0.ErrorMessage || "This artifact does not contain readable ML experiment results.");
36
+ } }
37
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_6_Template(rf, ctx) { if (rf & 1) {
38
+ i0.ɵɵelementStart(0, "div", 9);
39
+ i0.ɵɵtext(1);
40
+ i0.ɵɵelementEnd();
41
+ } if (rf & 2) {
42
+ const ctx_r0 = i0.ɵɵnextContext(2);
43
+ i0.ɵɵadvance();
44
+ i0.ɵɵtextInterpolate(ctx_r0.Summary);
45
+ } }
46
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_7_Template(rf, ctx) { if (rf & 1) {
47
+ i0.ɵɵelementStart(0, "div", 10)(1, "div", 31);
48
+ i0.ɵɵtext(2);
49
+ i0.ɵɵelementEnd();
50
+ i0.ɵɵelementStart(3, "div", 32);
51
+ i0.ɵɵtext(4);
52
+ i0.ɵɵelementEnd()();
53
+ } if (rf & 2) {
54
+ const ctx_r0 = i0.ɵɵnextContext(2);
55
+ i0.ɵɵadvance(2);
56
+ i0.ɵɵtextInterpolate(ctx_r0.HeadlineScore);
57
+ i0.ɵɵadvance(2);
58
+ i0.ɵɵtextInterpolate1("", ctx_r0.TargetMetricLabel, " \u00B7 winner");
59
+ } }
60
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_10_Template(rf, ctx) { if (rf & 1) {
61
+ i0.ɵɵelementStart(0, "div", 13)(1, "span", 33);
62
+ i0.ɵɵtext(2, "Goal");
63
+ i0.ɵɵelementEnd();
64
+ i0.ɵɵelementStart(3, "span", 34);
65
+ i0.ɵɵtext(4);
66
+ i0.ɵɵelementEnd()();
67
+ } if (rf & 2) {
68
+ const ctx_r0 = i0.ɵɵnextContext(2);
69
+ i0.ɵɵadvance(4);
70
+ i0.ɵɵtextInterpolate(ctx_r0.Goal);
71
+ } }
72
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_11_Template(rf, ctx) { if (rf & 1) {
73
+ i0.ɵɵelementStart(0, "div", 13)(1, "span", 33);
74
+ i0.ɵɵtext(2, "Target");
75
+ i0.ɵɵelementEnd();
76
+ i0.ɵɵelementStart(3, "span", 34);
77
+ i0.ɵɵtext(4);
78
+ i0.ɵɵelementEnd()();
79
+ } if (rf & 2) {
80
+ const ctx_r0 = i0.ɵɵnextContext(2);
81
+ i0.ɵɵadvance(4);
82
+ i0.ɵɵtextInterpolate(ctx_r0.Spec.target);
83
+ } }
84
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_12_Template(rf, ctx) { if (rf & 1) {
85
+ i0.ɵɵelementStart(0, "div", 13)(1, "span", 33);
86
+ i0.ɵɵtext(2, "As-of");
87
+ i0.ɵɵelementEnd();
88
+ i0.ɵɵelementStart(3, "span", 34);
89
+ i0.ɵɵtext(4);
90
+ i0.ɵɵelementEnd()();
91
+ } if (rf & 2) {
92
+ const ctx_r0 = i0.ɵɵnextContext(2);
93
+ i0.ɵɵadvance(4);
94
+ i0.ɵɵtextInterpolate(ctx_r0.Spec.asOf);
95
+ } }
96
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_13_Template(rf, ctx) { if (rf & 1) {
97
+ i0.ɵɵelementStart(0, "div", 13)(1, "span", 33);
98
+ i0.ɵɵtext(2, "Validation");
99
+ i0.ɵɵelementEnd();
100
+ i0.ɵɵelementStart(3, "span", 34);
101
+ i0.ɵɵtext(4);
102
+ i0.ɵɵelementEnd()();
103
+ } if (rf & 2) {
104
+ const ctx_r0 = i0.ɵɵnextContext(2);
105
+ i0.ɵɵadvance(4);
106
+ i0.ɵɵtextInterpolate(ctx_r0.Spec.validation);
107
+ } }
108
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_14_Template(rf, ctx) { if (rf & 1) {
109
+ i0.ɵɵelementStart(0, "div", 13)(1, "span", 33);
110
+ i0.ɵɵtext(2, "Budget used");
111
+ i0.ɵɵelementEnd();
112
+ i0.ɵɵelementStart(3, "span", 34);
113
+ i0.ɵɵtext(4);
114
+ i0.ɵɵelementEnd()();
115
+ } if (rf & 2) {
116
+ const ctx_r0 = i0.ɵɵnextContext(2);
117
+ i0.ɵɵadvance(4);
118
+ i0.ɵɵtextInterpolate(ctx_r0.Spec.budgetUsed);
119
+ } }
120
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_5_Template(rf, ctx) { if (rf & 1) {
121
+ i0.ɵɵelementStart(0, "strong");
122
+ i0.ɵɵtext(1);
123
+ i0.ɵɵelementEnd();
124
+ } if (rf & 2) {
125
+ const row_r4 = i0.ɵɵnextContext().$implicit;
126
+ i0.ɵɵadvance();
127
+ i0.ɵɵtextInterpolate(row_r4.algorithm);
128
+ } }
129
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_6_Template(rf, ctx) { if (rf & 1) {
130
+ i0.ɵɵtext(0);
131
+ } if (rf & 2) {
132
+ const row_r4 = i0.ɵɵnextContext().$implicit;
133
+ i0.ɵɵtextInterpolate1(" ", row_r4.algorithm, " ");
134
+ } }
135
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_7_Template(rf, ctx) { if (rf & 1) {
136
+ i0.ɵɵelement(0, "i", 42);
137
+ } }
138
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_11_Template(rf, ctx) { if (rf & 1) {
139
+ i0.ɵɵelementStart(0, "strong");
140
+ i0.ɵɵtext(1);
141
+ i0.ɵɵelementEnd();
142
+ } if (rf & 2) {
143
+ const row_r4 = i0.ɵɵnextContext().$implicit;
144
+ const ctx_r0 = i0.ɵɵnextContext(3);
145
+ i0.ɵɵadvance();
146
+ i0.ɵɵtextInterpolate(ctx_r0.formatScore(row_r4.score));
147
+ } }
148
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_12_Template(rf, ctx) { if (rf & 1) {
149
+ i0.ɵɵtext(0);
150
+ } if (rf & 2) {
151
+ const row_r4 = i0.ɵɵnextContext().$implicit;
152
+ const ctx_r0 = i0.ɵɵnextContext(3);
153
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.formatScore(row_r4.score), " ");
154
+ } }
155
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Template(rf, ctx) { if (rf & 1) {
156
+ const _r3 = i0.ɵɵgetCurrentView();
157
+ i0.ɵɵelementStart(0, "tr", 39);
158
+ i0.ɵɵlistener("click", function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Template_tr_click_0_listener() { const row_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r0 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r0.OnOpenRowModel(row_r4)); });
159
+ i0.ɵɵelementStart(1, "td")(2, "span", 40);
160
+ i0.ɵɵtext(3);
161
+ i0.ɵɵelementEnd()();
162
+ i0.ɵɵelementStart(4, "td", 41);
163
+ i0.ɵɵconditionalCreate(5, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_5_Template, 2, 1, "strong")(6, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_6_Template, 1, 1);
164
+ i0.ɵɵconditionalCreate(7, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_7_Template, 1, 0, "i", 42);
165
+ i0.ɵɵelementEnd();
166
+ i0.ɵɵelementStart(8, "td", 26);
167
+ i0.ɵɵtext(9);
168
+ i0.ɵɵelementEnd();
169
+ i0.ɵɵelementStart(10, "td", 37);
170
+ i0.ɵɵconditionalCreate(11, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_11_Template, 2, 1, "strong")(12, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Conditional_12_Template, 1, 1);
171
+ i0.ɵɵelementEnd();
172
+ i0.ɵɵelementStart(13, "td", 43);
173
+ i0.ɵɵtext(14);
174
+ i0.ɵɵelementEnd()();
175
+ } if (rf & 2) {
176
+ const row_r4 = ctx.$implicit;
177
+ const ctx_r0 = i0.ɵɵnextContext(3);
178
+ i0.ɵɵclassProp("is-winner", row_r4.isWinner)("has-model", row_r4.modelId);
179
+ i0.ɵɵadvance(2);
180
+ i0.ɵɵclassProp("gold", row_r4.isWinner);
181
+ i0.ɵɵadvance();
182
+ i0.ɵɵtextInterpolate(row_r4.rank);
183
+ i0.ɵɵadvance(2);
184
+ i0.ɵɵconditional(row_r4.isWinner ? 5 : 6);
185
+ i0.ɵɵadvance(2);
186
+ i0.ɵɵconditional(row_r4.modelId ? 7 : -1);
187
+ i0.ɵɵadvance(2);
188
+ i0.ɵɵtextInterpolate(row_r4.featureSet || "\u2014");
189
+ i0.ɵɵadvance(2);
190
+ i0.ɵɵconditional(row_r4.isWinner ? 11 : 12);
191
+ i0.ɵɵadvance(3);
192
+ i0.ɵɵtextInterpolate(ctx_r0.formatScore(row_r4.cvScore));
193
+ } }
194
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_Template(rf, ctx) { if (rf & 1) {
195
+ i0.ɵɵelementStart(0, "div", 17)(1, "table", 35)(2, "thead")(3, "tr")(4, "th", 36);
196
+ i0.ɵɵtext(5, "#");
197
+ i0.ɵɵelementEnd();
198
+ i0.ɵɵelementStart(6, "th");
199
+ i0.ɵɵtext(7, "Algorithm");
200
+ i0.ɵɵelementEnd();
201
+ i0.ɵɵelementStart(8, "th");
202
+ i0.ɵɵtext(9, "Feature set");
203
+ i0.ɵɵelementEnd();
204
+ i0.ɵɵelementStart(10, "th", 37);
205
+ i0.ɵɵtext(11);
206
+ i0.ɵɵelementEnd();
207
+ i0.ɵɵelementStart(12, "th", 37);
208
+ i0.ɵɵtext(13, "CV");
209
+ i0.ɵɵelementEnd()()();
210
+ i0.ɵɵelementStart(14, "tbody");
211
+ i0.ɵɵrepeaterCreate(15, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_For_16_Template, 15, 12, "tr", 38, _forTrack0);
212
+ i0.ɵɵelementEnd()()();
213
+ } if (rf & 2) {
214
+ const ctx_r0 = i0.ɵɵnextContext(2);
215
+ i0.ɵɵadvance(11);
216
+ i0.ɵɵtextInterpolate(ctx_r0.TargetMetricLabel);
217
+ i0.ɵɵadvance(4);
218
+ i0.ɵɵrepeater(ctx_r0.LeaderboardRows);
219
+ } }
220
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_20_Template(rf, ctx) { if (rf & 1) {
221
+ i0.ɵɵelementStart(0, "div", 18);
222
+ i0.ɵɵtext(1, "No leaderboard iterations were recorded.");
223
+ i0.ɵɵelementEnd();
224
+ } }
225
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_21_For_4_Template(rf, ctx) { if (rf & 1) {
226
+ i0.ɵɵelementStart(0, "div", 45)(1, "div", 46);
227
+ i0.ɵɵtext(2);
228
+ i0.ɵɵelementEnd();
229
+ i0.ɵɵelementStart(3, "div", 47);
230
+ i0.ɵɵelement(4, "span", 48);
231
+ i0.ɵɵelementEnd();
232
+ i0.ɵɵelementStart(5, "div", 49);
233
+ i0.ɵɵtext(6);
234
+ i0.ɵɵelementEnd()();
235
+ } if (rf & 2) {
236
+ const bar_r5 = ctx.$implicit;
237
+ const ctx_r0 = i0.ɵɵnextContext(3);
238
+ i0.ɵɵadvance();
239
+ i0.ɵɵproperty("title", bar_r5.feature);
240
+ i0.ɵɵadvance();
241
+ i0.ɵɵtextInterpolate(bar_r5.feature);
242
+ i0.ɵɵadvance(2);
243
+ i0.ɵɵstyleProp("width", bar_r5.widthPct, "%");
244
+ i0.ɵɵadvance(2);
245
+ i0.ɵɵtextInterpolate(ctx_r0.formatImportance(bar_r5.importance));
246
+ } }
247
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_21_Template(rf, ctx) { if (rf & 1) {
248
+ i0.ɵɵelementStart(0, "div", 16);
249
+ i0.ɵɵtext(1, "Feature Importance \u2014 winning model");
250
+ i0.ɵɵelementEnd();
251
+ i0.ɵɵelementStart(2, "div", 44);
252
+ i0.ɵɵrepeaterCreate(3, MLExperimentResultsViewerComponent_Conditional_3_Conditional_21_For_4_Template, 7, 5, "div", 45, _forTrack1);
253
+ i0.ɵɵelementEnd();
254
+ } if (rf & 2) {
255
+ const ctx_r0 = i0.ɵɵnextContext(2);
256
+ i0.ɵɵadvance(3);
257
+ i0.ɵɵrepeater(ctx_r0.FeatureBars);
258
+ } }
259
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_32_Template(rf, ctx) { if (rf & 1) {
260
+ i0.ɵɵelementStart(0, "div", 26);
261
+ i0.ɵɵtext(1);
262
+ i0.ɵɵelementEnd();
263
+ } if (rf & 2) {
264
+ const ctx_r0 = i0.ɵɵnextContext(2);
265
+ i0.ɵɵadvance();
266
+ i0.ɵɵtextInterpolate(ctx_r0.WinningModelSubtitle);
267
+ } }
268
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_33_For_2_Template(rf, ctx) { if (rf & 1) {
269
+ i0.ɵɵelementStart(0, "div", 50)(1, "div", 51);
270
+ i0.ɵɵtext(2);
271
+ i0.ɵɵelementEnd();
272
+ i0.ɵɵelementStart(3, "div", 52);
273
+ i0.ɵɵtext(4);
274
+ i0.ɵɵelementEnd()();
275
+ } if (rf & 2) {
276
+ const m_r6 = ctx.$implicit;
277
+ i0.ɵɵadvance(2);
278
+ i0.ɵɵtextInterpolate(m_r6.value);
279
+ i0.ɵɵadvance(2);
280
+ i0.ɵɵtextInterpolate(m_r6.label);
281
+ } }
282
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_33_Template(rf, ctx) { if (rf & 1) {
283
+ i0.ɵɵelementStart(0, "div", 27);
284
+ i0.ɵɵrepeaterCreate(1, MLExperimentResultsViewerComponent_Conditional_3_Conditional_33_For_2_Template, 5, 2, "div", 50, _forTrack2);
285
+ i0.ɵɵelementEnd();
286
+ } if (rf & 2) {
287
+ const ctx_r0 = i0.ɵɵnextContext(2);
288
+ i0.ɵɵadvance();
289
+ i0.ɵɵrepeater(ctx_r0.WinningMetrics);
290
+ } }
291
+ function MLExperimentResultsViewerComponent_Conditional_3_Conditional_37_Template(rf, ctx) { if (rf & 1) {
292
+ i0.ɵɵelementStart(0, "div", 30);
293
+ i0.ɵɵtext(1, " No linked ML Model record on this artifact yet. ");
294
+ i0.ɵɵelementEnd();
295
+ } }
296
+ function MLExperimentResultsViewerComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
297
+ const _r2 = i0.ɵɵgetCurrentView();
298
+ i0.ɵɵelementStart(0, "div", 5)(1, "div", 6);
299
+ i0.ɵɵelement(2, "i", 4);
300
+ i0.ɵɵelementEnd();
301
+ i0.ɵɵelementStart(3, "div", 7)(4, "h2", 8);
302
+ i0.ɵɵtext(5, "ML Experiment Results");
303
+ i0.ɵɵelementEnd();
304
+ i0.ɵɵconditionalCreate(6, MLExperimentResultsViewerComponent_Conditional_3_Conditional_6_Template, 2, 1, "div", 9);
305
+ i0.ɵɵelementEnd();
306
+ i0.ɵɵconditionalCreate(7, MLExperimentResultsViewerComponent_Conditional_3_Conditional_7_Template, 5, 2, "div", 10);
307
+ i0.ɵɵelementEnd();
308
+ i0.ɵɵelementStart(8, "div", 11)(9, "div", 12);
309
+ i0.ɵɵconditionalCreate(10, MLExperimentResultsViewerComponent_Conditional_3_Conditional_10_Template, 5, 1, "div", 13);
310
+ i0.ɵɵconditionalCreate(11, MLExperimentResultsViewerComponent_Conditional_3_Conditional_11_Template, 5, 1, "div", 13);
311
+ i0.ɵɵconditionalCreate(12, MLExperimentResultsViewerComponent_Conditional_3_Conditional_12_Template, 5, 1, "div", 13);
312
+ i0.ɵɵconditionalCreate(13, MLExperimentResultsViewerComponent_Conditional_3_Conditional_13_Template, 5, 1, "div", 13);
313
+ i0.ɵɵconditionalCreate(14, MLExperimentResultsViewerComponent_Conditional_3_Conditional_14_Template, 5, 1, "div", 13);
314
+ i0.ɵɵelementEnd();
315
+ i0.ɵɵelementStart(15, "div", 14)(16, "div", 15)(17, "div", 16);
316
+ i0.ɵɵtext(18, "Leaderboard");
317
+ i0.ɵɵelementEnd();
318
+ i0.ɵɵconditionalCreate(19, MLExperimentResultsViewerComponent_Conditional_3_Conditional_19_Template, 17, 1, "div", 17)(20, MLExperimentResultsViewerComponent_Conditional_3_Conditional_20_Template, 2, 0, "div", 18);
319
+ i0.ɵɵconditionalCreate(21, MLExperimentResultsViewerComponent_Conditional_3_Conditional_21_Template, 5, 0);
320
+ i0.ɵɵelementEnd();
321
+ i0.ɵɵelementStart(22, "div", 19)(23, "div", 16);
322
+ i0.ɵɵtext(24, "Winning Model");
323
+ i0.ɵɵelementEnd();
324
+ i0.ɵɵelementStart(25, "div", 20)(26, "div", 21)(27, "div", 22);
325
+ i0.ɵɵelement(28, "i", 23);
326
+ i0.ɵɵelementEnd();
327
+ i0.ɵɵelementStart(29, "div", 24)(30, "h3", 25);
328
+ i0.ɵɵtext(31);
329
+ i0.ɵɵelementEnd();
330
+ i0.ɵɵconditionalCreate(32, MLExperimentResultsViewerComponent_Conditional_3_Conditional_32_Template, 2, 1, "div", 26);
331
+ i0.ɵɵelementEnd()();
332
+ i0.ɵɵconditionalCreate(33, MLExperimentResultsViewerComponent_Conditional_3_Conditional_33_Template, 3, 0, "div", 27);
333
+ i0.ɵɵelementStart(34, "button", 28);
334
+ i0.ɵɵlistener("click", function MLExperimentResultsViewerComponent_Conditional_3_Template_button_click_34_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnDrillThroughToModel()); });
335
+ i0.ɵɵelement(35, "i", 29);
336
+ i0.ɵɵtext(36, " Drill through to ML Model ");
337
+ i0.ɵɵelementEnd();
338
+ i0.ɵɵconditionalCreate(37, MLExperimentResultsViewerComponent_Conditional_3_Conditional_37_Template, 2, 0, "div", 30);
339
+ i0.ɵɵelementEnd()()()();
340
+ } if (rf & 2) {
341
+ const ctx_r0 = i0.ɵɵnextContext();
342
+ i0.ɵɵadvance(6);
343
+ i0.ɵɵconditional(ctx_r0.Summary ? 6 : -1);
344
+ i0.ɵɵadvance();
345
+ i0.ɵɵconditional(ctx_r0.HeadlineScore != null ? 7 : -1);
346
+ i0.ɵɵadvance(3);
347
+ i0.ɵɵconditional(ctx_r0.Goal ? 10 : -1);
348
+ i0.ɵɵadvance();
349
+ i0.ɵɵconditional(ctx_r0.Spec.target ? 11 : -1);
350
+ i0.ɵɵadvance();
351
+ i0.ɵɵconditional(ctx_r0.Spec.asOf ? 12 : -1);
352
+ i0.ɵɵadvance();
353
+ i0.ɵɵconditional(ctx_r0.Spec.validation ? 13 : -1);
354
+ i0.ɵɵadvance();
355
+ i0.ɵɵconditional(ctx_r0.Spec.budgetUsed ? 14 : -1);
356
+ i0.ɵɵadvance(5);
357
+ i0.ɵɵconditional(ctx_r0.LeaderboardRows.length > 0 ? 19 : 20);
358
+ i0.ɵɵadvance(2);
359
+ i0.ɵɵconditional(ctx_r0.FeatureBars.length > 0 ? 21 : -1);
360
+ i0.ɵɵadvance(10);
361
+ i0.ɵɵtextInterpolate(ctx_r0.WinningAlgorithm);
362
+ i0.ɵɵadvance();
363
+ i0.ɵɵconditional(ctx_r0.WinningModelSubtitle ? 32 : -1);
364
+ i0.ɵɵadvance();
365
+ i0.ɵɵconditional(ctx_r0.WinningMetrics.length > 0 ? 33 : -1);
366
+ i0.ɵɵadvance();
367
+ i0.ɵɵproperty("disabled", !ctx_r0.HasDrillThroughTarget);
368
+ i0.ɵɵadvance(3);
369
+ i0.ɵɵconditional(!ctx_r0.HasDrillThroughTarget ? 37 : -1);
370
+ } }
371
+ /**
372
+ * Viewer plugin for **ML Experiment Results** artifacts (Predictive Studio).
373
+ *
374
+ * Renders the experiment goal + headline best metric, a ranked leaderboard of
375
+ * iterations, feature-importance bars for the winning model, and a winning-model
376
+ * card with a drill-through button that issues a {@link NavigationRequest} to open
377
+ * the winning `MJ: ML Models` record in Predictive Studio's "Models" nav item.
378
+ *
379
+ * Falls back to a friendly empty state when the JSON can't be parsed, and exposes
380
+ * the agent-authored markdown report as an additional "Report" tab when present.
381
+ */
382
+ let MLExperimentResultsViewerComponent = class MLExperimentResultsViewerComponent extends BaseArtifactViewerPluginComponent {
383
+ /** Emitted to request app-level navigation (drill-through to the ML Model record). */
384
+ navigationRequest = new EventEmitter();
385
+ cdr = inject(ChangeDetectorRef);
386
+ /** Parsed artifact content. */
387
+ Spec = null;
388
+ IsLoading = true;
389
+ HasError = false;
390
+ ErrorMessage = '';
391
+ /** Normalized, ranked leaderboard rows for rendering. */
392
+ LeaderboardRows = [];
393
+ /** Normalized feature-importance bars for rendering. */
394
+ FeatureBars = [];
395
+ // ─── Lifecycle ───────────────────────────────────────────────────
396
+ ngOnInit() {
397
+ try {
398
+ this.Spec = this.parseJsonContent();
399
+ if (!this.Spec) {
400
+ this.HasError = true;
401
+ this.ErrorMessage = 'Could not parse the ML Experiment Results content as JSON.';
402
+ return;
403
+ }
404
+ this.LeaderboardRows = this.buildLeaderboardRows(this.Spec.Leaderboard ?? this.Spec.leaderboard ?? []);
405
+ this.FeatureBars = this.buildFeatureBars(this.Spec.FeatureImportance ?? this.Spec.featureImportance ?? []);
406
+ }
407
+ catch (error) {
408
+ this.HasError = true;
409
+ this.ErrorMessage = error instanceof Error ? error.message : 'Failed to load experiment results.';
410
+ }
411
+ finally {
412
+ this.IsLoading = false;
413
+ this.cdr.detectChanges();
414
+ }
415
+ }
416
+ // ─── Base-class contract ─────────────────────────────────────────
417
+ get hasDisplayContent() {
418
+ return this.Spec != null;
419
+ }
420
+ GetCurrentStateSnapshot() {
421
+ // The richest portable representation is the agent-authored markdown report.
422
+ return createMarkdownSnapshot(this.WinningMarkdown ?? this.getRawContent(), this.getDisplayTitle());
423
+ }
424
+ /**
425
+ * Expose the agent-authored markdown report as an additional "Report" tab
426
+ * so users can read the full narrative alongside the rich visual display.
427
+ */
428
+ GetAdditionalTabs() {
429
+ const markdown = this.Spec?.Markdown ?? this.Spec?.report?.markdown;
430
+ if (!markdown) {
431
+ return [];
432
+ }
433
+ return [
434
+ {
435
+ label: 'Report',
436
+ icon: 'fa-file-lines',
437
+ contentType: 'markdown',
438
+ content: markdown
439
+ }
440
+ ];
441
+ }
442
+ // ─── Display getters ─────────────────────────────────────────────
443
+ get Goal() {
444
+ return this.Spec?.Goal ?? this.Spec?.goal ?? this.Spec?.Summary ?? this.Spec?.report?.summary ?? '';
445
+ }
446
+ get Summary() {
447
+ return this.Spec?.Summary ?? this.Spec?.report?.summary ?? '';
448
+ }
449
+ get TargetMetricLabel() {
450
+ return this.Spec?.TargetMetric ?? this.Spec?.targetMetric ?? this.firstMetricName() ?? 'Score';
451
+ }
452
+ /** The winning row (rank 1) if any. */
453
+ get WinningRow() {
454
+ return this.LeaderboardRows.find(r => r.isWinner) ?? this.LeaderboardRows[0] ?? null;
455
+ }
456
+ /** Headline best score (the winning row's primary score), formatted. */
457
+ get HeadlineScore() {
458
+ const score = this.WinningRow?.score;
459
+ return score != null ? this.formatScore(score) : null;
460
+ }
461
+ get WinningAlgorithm() {
462
+ return this.Spec?.BestModel?.Name ?? this.Spec?.report?.bestModelName ?? this.WinningRow?.algorithm ?? 'Winning model';
463
+ }
464
+ get WinningModelSubtitle() {
465
+ const parts = [];
466
+ if (this.WinningRow?.featureSet) {
467
+ parts.push(this.WinningRow.featureSet);
468
+ }
469
+ const version = this.Spec?.BestModel?.Version ?? this.Spec?.report?.bestModelVersion;
470
+ if (version != null && `${version}`.trim()) {
471
+ parts.push(`${version}`);
472
+ }
473
+ return parts.join(' · ');
474
+ }
475
+ /** Extra headline metrics for the winning-model card. */
476
+ get WinningMetrics() {
477
+ const provided = this.Spec?.winningMetrics ?? [];
478
+ if (provided.length > 0) {
479
+ return provided;
480
+ }
481
+ // Synthesize a single metric from the headline score when nothing explicit was provided.
482
+ const row = this.WinningRow;
483
+ if (row?.score != null) {
484
+ return [{ label: this.firstMetricName() ?? 'Score', value: this.formatScore(row.score) }];
485
+ }
486
+ return [];
487
+ }
488
+ get WinningMarkdown() {
489
+ return this.Spec?.Markdown ?? this.Spec?.report?.markdown ?? null;
490
+ }
491
+ /** Whether we have a resolvable model ID to drill through to. */
492
+ get HasDrillThroughTarget() {
493
+ return this.resolveBestModelId() != null;
494
+ }
495
+ get LeaderboardSize() {
496
+ return this.LeaderboardRows.length;
497
+ }
498
+ // ─── Actions ─────────────────────────────────────────────────────
499
+ /**
500
+ * Drill through to the winning ML Model record in Predictive Studio.
501
+ * Matches the §9.4 contract: NavigationRequest to the 'Models' nav item.
502
+ */
503
+ OnDrillThroughToModel() {
504
+ const modelId = this.resolveBestModelId();
505
+ if (!modelId) {
506
+ return;
507
+ }
508
+ this.navigationRequest.emit({
509
+ appName: 'Predictive Studio',
510
+ navItemName: 'Models',
511
+ queryParams: { modelId }
512
+ });
513
+ }
514
+ /**
515
+ * Drill through to a specific leaderboard row's model, when that row carries a modelId.
516
+ */
517
+ OnOpenRowModel(row) {
518
+ if (!row.modelId) {
519
+ return;
520
+ }
521
+ this.navigationRequest.emit({
522
+ appName: 'Predictive Studio',
523
+ navItemName: 'Models',
524
+ queryParams: { modelId: row.modelId }
525
+ });
526
+ }
527
+ // ─── Helpers ─────────────────────────────────────────────────────
528
+ /**
529
+ * Resolve the winning model ID. Priority (canonical PascalCase first):
530
+ * BestModel.ID → BestModelID → report block → lowercase field → top leaderboard row.
531
+ */
532
+ resolveBestModelId() {
533
+ return this.Spec?.BestModel?.ID
534
+ ?? this.Spec?.BestModelID
535
+ ?? this.Spec?.report?.bestModelId
536
+ ?? this.Spec?.bestModelId
537
+ ?? this.WinningRow?.modelId
538
+ ?? null;
539
+ }
540
+ /** Build normalized, ranked leaderboard rows from raw entries. */
541
+ buildLeaderboardRows(entries) {
542
+ if (!Array.isArray(entries) || entries.length === 0) {
543
+ return [];
544
+ }
545
+ const rows = entries.map((e, index) => ({
546
+ // Canonical `Leaderboard` is already best-first; derive rank from order.
547
+ rank: e.rank ?? index + 1,
548
+ algorithm: e.algorithm ?? e.algorithmName ?? 'Unknown',
549
+ featureSet: e.featureSet ?? '',
550
+ // Canonical: `Metric`; fallback: lowercase `score`.
551
+ score: this.firstDefined(e.Metric ?? e.score),
552
+ cvScore: this.firstDefined(e.cvScore),
553
+ // Canonical: `ModelID`; fallback: lowercase `modelId`.
554
+ modelId: e.ModelID ?? e.modelId ?? null,
555
+ isWinner: false
556
+ }));
557
+ // Sort by explicit rank ascending (rank 1 is best).
558
+ rows.sort((a, b) => a.rank - b.rank);
559
+ if (rows.length > 0) {
560
+ rows[0].isWinner = true;
561
+ }
562
+ return rows;
563
+ }
564
+ /** Build normalized feature-importance bars (widths relative to the max). */
565
+ buildFeatureBars(entries) {
566
+ if (!Array.isArray(entries) || entries.length === 0) {
567
+ return [];
568
+ }
569
+ const resolved = entries.map(e => ({
570
+ feature: e.feature ?? e.name ?? 'Feature',
571
+ importance: this.firstDefined(e.importance ?? e.weight ?? e.value) ?? 0
572
+ }));
573
+ const max = resolved.reduce((m, r) => Math.max(m, r.importance), 0);
574
+ // Sort descending by importance for a clean ranked bar chart.
575
+ resolved.sort((a, b) => b.importance - a.importance);
576
+ return resolved.map(r => ({
577
+ feature: r.feature,
578
+ importance: r.importance,
579
+ widthPct: max > 0 ? Math.max(2, Math.round((r.importance / max) * 100)) : 0
580
+ }));
581
+ }
582
+ /** First metric name found on the leaderboard, for column/label fallback. */
583
+ firstMetricName() {
584
+ const entry = (this.Spec?.Leaderboard ?? this.Spec?.leaderboard)?.[0];
585
+ return entry?.metricName ?? null;
586
+ }
587
+ /** Return the value if it's a finite number, else null. */
588
+ firstDefined(value) {
589
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
590
+ }
591
+ /** Format a numeric score for display (3 decimals, trimmed). */
592
+ formatScore(value) {
593
+ if (value == null) {
594
+ return '—';
595
+ }
596
+ // Scores in [0,1] (AUC/F1) look best at 3 decimals; larger metrics (RMSE) at 2.
597
+ const decimals = Math.abs(value) < 1 ? 3 : 2;
598
+ return value.toFixed(decimals);
599
+ }
600
+ /** Format an importance weight for the small bar label. */
601
+ formatImportance(value) {
602
+ if (!Number.isFinite(value)) {
603
+ return '';
604
+ }
605
+ // Show .31 style for sub-1 weights, otherwise 2 decimals.
606
+ return Math.abs(value) < 1 ? value.toFixed(2).replace(/^0/, '') : value.toFixed(2);
607
+ }
608
+ static ɵfac = /*@__PURE__*/ (() => { let ɵMLExperimentResultsViewerComponent_BaseFactory; return function MLExperimentResultsViewerComponent_Factory(__ngFactoryType__) { return (ɵMLExperimentResultsViewerComponent_BaseFactory || (ɵMLExperimentResultsViewerComponent_BaseFactory = i0.ɵɵgetInheritedFactory(MLExperimentResultsViewerComponent)))(__ngFactoryType__ || MLExperimentResultsViewerComponent); }; })();
609
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MLExperimentResultsViewerComponent, selectors: [["mj-ml-experiment-results-viewer"]], outputs: { navigationRequest: "navigationRequest" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [[1, "ml-exp-viewer", 3, "ngClass"], [1, "ml-exp-loading"], [1, "ml-exp-empty"], ["text", "Loading experiment results\u2026", "size", "medium"], [1, "fa-solid", "fa-flask-vial"], [1, "ml-exp-hero"], [1, "hero-badge"], [1, "hero-titles"], [1, "hero-title"], [1, "hero-sub"], [1, "hero-metric"], [1, "ml-exp-body"], [1, "goalbar"], [1, "goal-item"], [1, "ml-exp-cols"], [1, "col-main"], [1, "section-title"], [1, "lb-card"], [1, "inline-empty"], [1, "col-side"], [1, "winner-card"], [1, "winner-top"], [1, "crown"], [1, "fa-solid", "fa-crown"], [1, "winner-head"], [1, "winner-name"], [1, "muted"], [1, "wmetrics"], ["mjButton", "", "variant", "primary", 1, "drill-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "drill-hint", "muted"], [1, "hero-metric-value"], [1, "hero-metric-label"], [1, "goal-key"], [1, "goal-val"], [1, "lb-table"], [1, "lb-rank-col"], [1, "num"], [3, "is-winner", "has-model"], [3, "click"], [1, "rank"], [1, "algo"], ["title", "Open this model", 1, "fa-solid", "fa-arrow-up-right-from-square", "row-link-icon"], [1, "num", "muted"], [1, "fi-card"], [1, "fbar"], [1, "fbar-label", 3, "title"], [1, "fbar-track"], [1, "fbar-fill"], [1, "fbar-num"], [1, "wmetric"], [1, "wmetric-value"], [1, "wmetric-label"]], template: function MLExperimentResultsViewerComponent_Template(rf, ctx) { if (rf & 1) {
610
+ i0.ɵɵelementStart(0, "div", 0);
611
+ i0.ɵɵconditionalCreate(1, MLExperimentResultsViewerComponent_Conditional_1_Template, 2, 0, "div", 1)(2, MLExperimentResultsViewerComponent_Conditional_2_Template, 6, 1, "div", 2)(3, MLExperimentResultsViewerComponent_Conditional_3_Template, 38, 14);
612
+ i0.ɵɵelementEnd();
613
+ } if (rf & 2) {
614
+ i0.ɵɵproperty("ngClass", ctx.cssClass);
615
+ i0.ɵɵadvance();
616
+ i0.ɵɵconditional(ctx.IsLoading ? 1 : ctx.HasError || !ctx.Spec ? 2 : 3);
617
+ } }, dependencies: [i1.NgClass, i2.LoadingComponent, i3.MJButtonDirective], styles: ["[_nghost-%COMP%] {\n display: block;\n height: 100%;\n}\n\n.ml-exp-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n font-size: 13px;\n}\n\n\n\n\n.ml-exp-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n}\n\n.ml-exp-empty[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 240px;\n padding: 40px 24px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.ml-exp-empty[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 40px;\n margin-bottom: 14px;\n color: var(--mj-text-disabled);\n}\n\n.ml-exp-empty[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 6px;\n font-size: 16px;\n color: var(--mj-text-secondary);\n}\n\n.ml-exp-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n max-width: 420px;\n font-size: 13px;\n}\n\n\n\n\n.ml-exp-hero[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px 22px;\n color: var(--mj-text-inverse);\n background: linear-gradient(135deg, var(--mj-brand-primary-active), var(--mj-brand-primary));\n}\n\n.hero-badge[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: grid;\n place-items: center;\n font-size: 20px;\n background: color-mix(in srgb, var(--mj-text-inverse) 16%, transparent);\n}\n\n.hero-titles[_ngcontent-%COMP%] {\n min-width: 0;\n}\n\n.hero-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n}\n\n.hero-sub[_ngcontent-%COMP%] {\n margin-top: 3px;\n font-size: 12.5px;\n color: color-mix(in srgb, var(--mj-text-inverse) 78%, transparent);\n}\n\n.hero-metric[_ngcontent-%COMP%] {\n margin-left: auto;\n text-align: right;\n flex: 0 0 auto;\n}\n\n.hero-metric-value[_ngcontent-%COMP%] {\n font-size: 34px;\n font-weight: 780;\n letter-spacing: -0.02em;\n line-height: 1;\n}\n\n.hero-metric-label[_ngcontent-%COMP%] {\n margin-top: 4px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: color-mix(in srgb, var(--mj-text-inverse) 72%, transparent);\n}\n\n\n\n\n.ml-exp-body[_ngcontent-%COMP%] {\n padding: 20px 22px 28px;\n background: var(--mj-bg-surface);\n flex: 1;\n}\n\n.goalbar[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 10px 26px;\n padding: 13px 16px;\n margin-bottom: 18px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.goal-item[_ngcontent-%COMP%] {\n font-size: 12.5px;\n min-width: 0;\n}\n\n.goal-key[_ngcontent-%COMP%] {\n display: block;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n}\n\n.goal-val[_ngcontent-%COMP%] {\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n\n.ml-exp-cols[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1.25fr 1fr;\n gap: 20px;\n align-items: start;\n}\n\n@media (max-width: 920px) {\n .ml-exp-cols[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n}\n\n.section-title[_ngcontent-%COMP%] {\n margin: 0 0 10px;\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-secondary);\n}\n\n.col-main[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%]:not(:first-child) {\n margin-top: 20px;\n}\n\n.inline-empty[_ngcontent-%COMP%] {\n padding: 14px 16px;\n border: 1px dashed var(--mj-border-default);\n border-radius: 10px;\n color: var(--mj-text-muted);\n font-size: 12.5px;\n}\n\n\n\n\n.lb-card[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.lb-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 12.5px;\n}\n\n.lb-table[_ngcontent-%COMP%] thead[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left;\n padding: 10px 12px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:last-child td[_ngcontent-%COMP%] {\n border-bottom: 0;\n}\n\n.lb-table[_ngcontent-%COMP%] .num[_ngcontent-%COMP%] {\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.lb-table[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.lb-table[_ngcontent-%COMP%] .lb-rank-col[_ngcontent-%COMP%] {\n width: 44px;\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.is-winner[_ngcontent-%COMP%] {\n background: var(--mj-status-success-bg);\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.has-model[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.has-model[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.has-model.is-winner[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-success) 14%, var(--mj-bg-surface));\n}\n\n.row-link-icon[_ngcontent-%COMP%] {\n margin-left: 6px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n}\n\n.lb-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr.has-model[_ngcontent-%COMP%]:hover .row-link-icon[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n\n.rank[_ngcontent-%COMP%] {\n display: inline-grid;\n place-items: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.rank.gold[_ngcontent-%COMP%] {\n color: var(--mj-status-warning-text);\n background: var(--mj-status-warning-bg);\n}\n\n\n\n\n.fi-card[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 14px 16px;\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.fbar[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 2fr auto;\n align-items: center;\n gap: 12px;\n font-size: 12.5px;\n}\n\n.fbar-label[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.fbar-track[_ngcontent-%COMP%] {\n height: 8px;\n border-radius: 999px;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.fbar-fill[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n border-radius: 999px;\n background: var(--mj-brand-primary);\n transition: width 0.25s ease;\n}\n\n.fbar-num[_ngcontent-%COMP%] {\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-muted);\n min-width: 30px;\n text-align: right;\n}\n\n\n\n\n.winner-card[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-status-success-border);\n border-radius: 12px;\n padding: 18px;\n background: color-mix(in srgb, var(--mj-status-success) 6%, var(--mj-bg-surface));\n}\n\n.winner-top[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 13px;\n}\n\n.crown[_ngcontent-%COMP%] {\n flex: 0 0 auto;\n width: 46px;\n height: 46px;\n border-radius: 11px;\n display: grid;\n place-items: center;\n font-size: 19px;\n color: var(--mj-text-inverse);\n background: var(--mj-status-success);\n}\n\n.winner-head[_ngcontent-%COMP%] {\n min-width: 0;\n}\n\n.winner-name[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.winner-head[_ngcontent-%COMP%] .muted[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.wmetrics[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));\n gap: 10px;\n margin: 16px 0;\n}\n\n.wmetric[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-subtle);\n border-radius: 9px;\n padding: 10px 12px;\n text-align: center;\n background: var(--mj-bg-surface);\n}\n\n.wmetric-value[_ngcontent-%COMP%] {\n font-size: 19px;\n font-weight: 720;\n color: var(--mj-status-success-text);\n}\n\n.wmetric-label[_ngcontent-%COMP%] {\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.drill-btn[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: center;\n}\n\n.drill-hint[_ngcontent-%COMP%] {\n margin-top: 8px;\n font-size: 11.5px;\n text-align: center;\n color: var(--mj-text-muted);\n}"] });
618
+ };
619
+ MLExperimentResultsViewerComponent = __decorate([
620
+ RegisterClass(BaseArtifactViewerPluginComponent, 'MLExperimentResultsViewerPlugin')
621
+ ], MLExperimentResultsViewerComponent);
622
+ export { MLExperimentResultsViewerComponent };
623
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MLExperimentResultsViewerComponent, [{
624
+ type: Component,
625
+ args: [{ standalone: false, selector: 'mj-ml-experiment-results-viewer', template: "<div class=\"ml-exp-viewer\" [ngClass]=\"cssClass\">\n\n @if (IsLoading) {\n <div class=\"ml-exp-loading\">\n <mj-loading text=\"Loading experiment results\u2026\" size=\"medium\"></mj-loading>\n </div>\n } @else if (HasError || !Spec) {\n <div class=\"ml-exp-empty\">\n <i class=\"fa-solid fa-flask-vial\"></i>\n <h3>No experiment results to display</h3>\n <p>{{ ErrorMessage || 'This artifact does not contain readable ML experiment results.' }}</p>\n </div>\n } @else {\n\n <!-- HERO -->\n <div class=\"ml-exp-hero\">\n <div class=\"hero-badge\"><i class=\"fa-solid fa-flask-vial\"></i></div>\n <div class=\"hero-titles\">\n <h2 class=\"hero-title\">ML Experiment Results</h2>\n @if (Summary) {\n <div class=\"hero-sub\">{{ Summary }}</div>\n }\n </div>\n @if (HeadlineScore != null) {\n <div class=\"hero-metric\">\n <div class=\"hero-metric-value\">{{ HeadlineScore }}</div>\n <div class=\"hero-metric-label\">{{ TargetMetricLabel }} \u00B7 winner</div>\n </div>\n }\n </div>\n\n <div class=\"ml-exp-body\">\n\n <!-- GOAL BAR -->\n <div class=\"goalbar\">\n @if (Goal) {\n <div class=\"goal-item\">\n <span class=\"goal-key\">Goal</span>\n <span class=\"goal-val\">{{ Goal }}</span>\n </div>\n }\n @if (Spec.target) {\n <div class=\"goal-item\">\n <span class=\"goal-key\">Target</span>\n <span class=\"goal-val\">{{ Spec.target }}</span>\n </div>\n }\n @if (Spec.asOf) {\n <div class=\"goal-item\">\n <span class=\"goal-key\">As-of</span>\n <span class=\"goal-val\">{{ Spec.asOf }}</span>\n </div>\n }\n @if (Spec.validation) {\n <div class=\"goal-item\">\n <span class=\"goal-key\">Validation</span>\n <span class=\"goal-val\">{{ Spec.validation }}</span>\n </div>\n }\n @if (Spec.budgetUsed) {\n <div class=\"goal-item\">\n <span class=\"goal-key\">Budget used</span>\n <span class=\"goal-val\">{{ Spec.budgetUsed }}</span>\n </div>\n }\n </div>\n\n <div class=\"ml-exp-cols\">\n\n <!-- LEFT COLUMN: leaderboard + feature importance -->\n <div class=\"col-main\">\n\n <div class=\"section-title\">Leaderboard</div>\n @if (LeaderboardRows.length > 0) {\n <div class=\"lb-card\">\n <table class=\"lb-table\">\n <thead>\n <tr>\n <th class=\"lb-rank-col\">#</th>\n <th>Algorithm</th>\n <th>Feature set</th>\n <th class=\"num\">{{ TargetMetricLabel }}</th>\n <th class=\"num\">CV</th>\n </tr>\n </thead>\n <tbody>\n @for (row of LeaderboardRows; track row.rank) {\n <tr [class.is-winner]=\"row.isWinner\"\n [class.has-model]=\"row.modelId\"\n (click)=\"OnOpenRowModel(row)\">\n <td>\n <span class=\"rank\" [class.gold]=\"row.isWinner\">{{ row.rank }}</span>\n </td>\n <td class=\"algo\">\n @if (row.isWinner) {\n <strong>{{ row.algorithm }}</strong>\n } @else {\n {{ row.algorithm }}\n }\n @if (row.modelId) {\n <i class=\"fa-solid fa-arrow-up-right-from-square row-link-icon\"\n title=\"Open this model\"></i>\n }\n </td>\n <td class=\"muted\">{{ row.featureSet || '\u2014' }}</td>\n <td class=\"num\">\n @if (row.isWinner) {\n <strong>{{ formatScore(row.score) }}</strong>\n } @else {\n {{ formatScore(row.score) }}\n }\n </td>\n <td class=\"num muted\">{{ formatScore(row.cvScore) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n } @else {\n <div class=\"inline-empty\">No leaderboard iterations were recorded.</div>\n }\n\n @if (FeatureBars.length > 0) {\n <div class=\"section-title\">Feature Importance \u2014 winning model</div>\n <div class=\"fi-card\">\n @for (bar of FeatureBars; track bar.feature) {\n <div class=\"fbar\">\n <div class=\"fbar-label\" [title]=\"bar.feature\">{{ bar.feature }}</div>\n <div class=\"fbar-track\">\n <span class=\"fbar-fill\" [style.width.%]=\"bar.widthPct\"></span>\n </div>\n <div class=\"fbar-num\">{{ formatImportance(bar.importance) }}</div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- RIGHT COLUMN: winning model card + drill-through -->\n <div class=\"col-side\">\n <div class=\"section-title\">Winning Model</div>\n <div class=\"winner-card\">\n <div class=\"winner-top\">\n <div class=\"crown\"><i class=\"fa-solid fa-crown\"></i></div>\n <div class=\"winner-head\">\n <h3 class=\"winner-name\">{{ WinningAlgorithm }}</h3>\n @if (WinningModelSubtitle) {\n <div class=\"muted\">{{ WinningModelSubtitle }}</div>\n }\n </div>\n </div>\n\n @if (WinningMetrics.length > 0) {\n <div class=\"wmetrics\">\n @for (m of WinningMetrics; track m.label) {\n <div class=\"wmetric\">\n <div class=\"wmetric-value\">{{ m.value }}</div>\n <div class=\"wmetric-label\">{{ m.label }}</div>\n </div>\n }\n </div>\n }\n\n <button mjButton variant=\"primary\" class=\"drill-btn\"\n [disabled]=\"!HasDrillThroughTarget\"\n (click)=\"OnDrillThroughToModel()\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i>\n Drill through to ML Model\n </button>\n\n @if (!HasDrillThroughTarget) {\n <div class=\"drill-hint muted\">\n No linked ML Model record on this artifact yet.\n </div>\n }\n </div>\n </div>\n\n </div>\n </div>\n }\n</div>\n", styles: [":host {\n display: block;\n height: 100%;\n}\n\n.ml-exp-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow-y: auto;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Loading / empty states \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.ml-exp-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 200px;\n}\n\n.ml-exp-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n flex: 1;\n min-height: 240px;\n padding: 40px 24px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.ml-exp-empty i {\n font-size: 40px;\n margin-bottom: 14px;\n color: var(--mj-text-disabled);\n}\n\n.ml-exp-empty h3 {\n margin: 0 0 6px;\n font-size: 16px;\n color: var(--mj-text-secondary);\n}\n\n.ml-exp-empty p {\n margin: 0;\n max-width: 420px;\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Hero \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.ml-exp-hero {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 20px 22px;\n color: var(--mj-text-inverse);\n background: linear-gradient(135deg, var(--mj-brand-primary-active), var(--mj-brand-primary));\n}\n\n.hero-badge {\n flex: 0 0 auto;\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: grid;\n place-items: center;\n font-size: 20px;\n background: color-mix(in srgb, var(--mj-text-inverse) 16%, transparent);\n}\n\n.hero-titles {\n min-width: 0;\n}\n\n.hero-title {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n}\n\n.hero-sub {\n margin-top: 3px;\n font-size: 12.5px;\n color: color-mix(in srgb, var(--mj-text-inverse) 78%, transparent);\n}\n\n.hero-metric {\n margin-left: auto;\n text-align: right;\n flex: 0 0 auto;\n}\n\n.hero-metric-value {\n font-size: 34px;\n font-weight: 780;\n letter-spacing: -0.02em;\n line-height: 1;\n}\n\n.hero-metric-label {\n margin-top: 4px;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: color-mix(in srgb, var(--mj-text-inverse) 72%, transparent);\n}\n\n/* \u2500\u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.ml-exp-body {\n padding: 20px 22px 28px;\n background: var(--mj-bg-surface);\n flex: 1;\n}\n\n.goalbar {\n display: flex;\n flex-wrap: wrap;\n gap: 10px 26px;\n padding: 13px 16px;\n margin-bottom: 18px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.goal-item {\n font-size: 12.5px;\n min-width: 0;\n}\n\n.goal-key {\n display: block;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n}\n\n.goal-val {\n font-weight: 650;\n color: var(--mj-text-primary);\n}\n\n.ml-exp-cols {\n display: grid;\n grid-template-columns: 1.25fr 1fr;\n gap: 20px;\n align-items: start;\n}\n\n@media (max-width: 920px) {\n .ml-exp-cols {\n grid-template-columns: 1fr;\n }\n}\n\n.section-title {\n margin: 0 0 10px;\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-text-secondary);\n}\n\n.col-main .section-title:not(:first-child) {\n margin-top: 20px;\n}\n\n.inline-empty {\n padding: 14px 16px;\n border: 1px dashed var(--mj-border-default);\n border-radius: 10px;\n color: var(--mj-text-muted);\n font-size: 12.5px;\n}\n\n/* \u2500\u2500\u2500 Leaderboard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.lb-card {\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.lb-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 12.5px;\n}\n\n.lb-table thead th {\n text-align: left;\n padding: 10px 12px;\n font-size: 11px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.lb-table tbody td {\n padding: 10px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-primary);\n}\n\n.lb-table tbody tr:last-child td {\n border-bottom: 0;\n}\n\n.lb-table .num {\n text-align: right;\n font-variant-numeric: tabular-nums;\n}\n\n.lb-table .muted {\n color: var(--mj-text-muted);\n}\n\n.lb-table .lb-rank-col {\n width: 44px;\n}\n\n.lb-table tbody tr.is-winner {\n background: var(--mj-status-success-bg);\n}\n\n.lb-table tbody tr.has-model {\n cursor: pointer;\n}\n\n.lb-table tbody tr.has-model:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.lb-table tbody tr.has-model.is-winner:hover {\n background: color-mix(in srgb, var(--mj-status-success) 14%, var(--mj-bg-surface));\n}\n\n.row-link-icon {\n margin-left: 6px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n}\n\n.lb-table tbody tr.has-model:hover .row-link-icon {\n color: var(--mj-brand-primary);\n}\n\n.rank {\n display: inline-grid;\n place-items: center;\n min-width: 22px;\n height: 22px;\n padding: 0 6px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n}\n\n.rank.gold {\n color: var(--mj-status-warning-text);\n background: var(--mj-status-warning-bg);\n}\n\n/* \u2500\u2500\u2500 Feature importance \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.fi-card {\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 14px 16px;\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.fbar {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 2fr auto;\n align-items: center;\n gap: 12px;\n font-size: 12.5px;\n}\n\n.fbar-label {\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.fbar-track {\n height: 8px;\n border-radius: 999px;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n.fbar-fill {\n display: block;\n height: 100%;\n border-radius: 999px;\n background: var(--mj-brand-primary);\n transition: width 0.25s ease;\n}\n\n.fbar-num {\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-muted);\n min-width: 30px;\n text-align: right;\n}\n\n/* \u2500\u2500\u2500 Winning model card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.winner-card {\n border: 1px solid var(--mj-status-success-border);\n border-radius: 12px;\n padding: 18px;\n background: color-mix(in srgb, var(--mj-status-success) 6%, var(--mj-bg-surface));\n}\n\n.winner-top {\n display: flex;\n align-items: center;\n gap: 13px;\n}\n\n.crown {\n flex: 0 0 auto;\n width: 46px;\n height: 46px;\n border-radius: 11px;\n display: grid;\n place-items: center;\n font-size: 19px;\n color: var(--mj-text-inverse);\n background: var(--mj-status-success);\n}\n\n.winner-head {\n min-width: 0;\n}\n\n.winner-name {\n margin: 0;\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.winner-head .muted {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.wmetrics {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));\n gap: 10px;\n margin: 16px 0;\n}\n\n.wmetric {\n border: 1px solid var(--mj-border-subtle);\n border-radius: 9px;\n padding: 10px 12px;\n text-align: center;\n background: var(--mj-bg-surface);\n}\n\n.wmetric-value {\n font-size: 19px;\n font-weight: 720;\n color: var(--mj-status-success-text);\n}\n\n.wmetric-label {\n margin-top: 2px;\n font-size: 11px;\n color: var(--mj-text-muted);\n}\n\n.drill-btn {\n width: 100%;\n justify-content: center;\n}\n\n.drill-hint {\n margin-top: 8px;\n font-size: 11.5px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n"] }]
626
+ }], null, { navigationRequest: [{
627
+ type: Output
628
+ }] }); })();
629
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MLExperimentResultsViewerComponent, { className: "MLExperimentResultsViewerComponent", filePath: "src/lib/components/plugins/ml-experiment-results-viewer.component.ts", lineNumber: 184 }); })();
630
+ //# sourceMappingURL=ml-experiment-results-viewer.component.js.map