@memberjunction/ng-dashboards 2.87.0 → 2.89.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.
@@ -4,214 +4,291 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { Component } from '@angular/core';
7
+ import { Component, ViewChild } from '@angular/core';
8
8
  import { BaseDashboard } from '../generic/base-dashboard';
9
9
  import { RegisterClass } from '@memberjunction/global';
10
10
  import { RunView } from '@memberjunction/core';
11
11
  import { Subject } from 'rxjs';
12
12
  import { SharedService } from '@memberjunction/ng-shared';
13
+ import { ParseJSONRecursive } from '@memberjunction/global';
13
14
  import * as i0 from "@angular/core";
14
15
  import * as i1 from "@angular/common";
15
- import * as i2 from "@progress/kendo-angular-inputs";
16
- import * as i3 from "@progress/kendo-angular-layout";
17
- import * as i4 from "@progress/kendo-angular-buttons";
18
- import * as i5 from "@memberjunction/ng-react";
19
- const _forTrack0 = ($index, $item) => $item.ID;
20
- function ComponentStudioDashboardComponent_ng_template_16_Template(rf, ctx) { if (rf & 1) {
21
- i0.ɵɵelement(0, "i", 18);
22
- } }
23
- function ComponentStudioDashboardComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
24
- i0.ɵɵelementStart(0, "div", 13);
25
- i0.ɵɵelement(1, "i", 19);
16
+ import * as i2 from "@angular/forms";
17
+ import * as i3 from "@progress/kendo-angular-inputs";
18
+ import * as i4 from "@progress/kendo-angular-layout";
19
+ import * as i5 from "@memberjunction/ng-code-editor";
20
+ import * as i6 from "@progress/kendo-angular-buttons";
21
+ import * as i7 from "@memberjunction/ng-react";
22
+ const _c0 = ["fileInput"];
23
+ function _forTrack0($index, $item) { return this.getComponentId($item); }
24
+ const _forTrack1 = ($index, $item) => $item.title;
25
+ function ComponentStudioDashboardComponent_Conditional_10_Conditional_1_Template(rf, ctx) { if (rf & 1) {
26
+ i0.ɵɵelement(0, "span", 27);
27
+ i0.ɵɵtext(1, " Show Details ");
28
+ } }
29
+ function ComponentStudioDashboardComponent_Conditional_10_Conditional_2_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelement(0, "span", 28);
31
+ i0.ɵɵtext(1, " Hide Details ");
32
+ } }
33
+ function ComponentStudioDashboardComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
34
+ const _r2 = i0.ɵɵgetCurrentView();
35
+ i0.ɵɵelementStart(0, "button", 8);
36
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_10_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleDetailsPane()); });
37
+ i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_10_Conditional_1_Template, 2, 0)(2, ComponentStudioDashboardComponent_Conditional_10_Conditional_2_Template, 2, 0);
38
+ i0.ɵɵelementEnd();
39
+ } if (rf & 2) {
40
+ const ctx_r2 = i0.ɵɵnextContext();
41
+ i0.ɵɵproperty("themeColor", "base");
42
+ i0.ɵɵadvance();
43
+ i0.ɵɵconditional(ctx_r2.isDetailsPaneCollapsed ? 1 : 2);
44
+ } }
45
+ function ComponentStudioDashboardComponent_ng_template_27_Template(rf, ctx) { if (rf & 1) {
46
+ i0.ɵɵelement(0, "i", 29);
47
+ } }
48
+ function ComponentStudioDashboardComponent_Conditional_29_Template(rf, ctx) { if (rf & 1) {
49
+ i0.ɵɵelementStart(0, "div", 21);
50
+ i0.ɵɵelement(1, "i", 30);
26
51
  i0.ɵɵtext(2, " Loading components... ");
27
52
  i0.ɵɵelementEnd();
28
53
  } }
29
- function ComponentStudioDashboardComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
30
- i0.ɵɵelementStart(0, "div", 14);
31
- i0.ɵɵtext(1, " No components found ");
54
+ function ComponentStudioDashboardComponent_Conditional_30_Template(rf, ctx) { if (rf & 1) {
55
+ i0.ɵɵelementStart(0, "div", 22);
56
+ i0.ɵɵelement(1, "i", 31);
57
+ i0.ɵɵtext(2, " No components found without custom properties. ");
58
+ i0.ɵɵelement(3, "br");
59
+ i0.ɵɵelementStart(4, "small");
60
+ i0.ɵɵtext(5, "Only components that don't require custom props can be tested here.");
61
+ i0.ɵɵelementEnd()();
62
+ } }
63
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_7_Template(rf, ctx) { if (rf & 1) {
64
+ i0.ɵɵelementStart(0, "span", 39);
65
+ i0.ɵɵelement(1, "i", 50);
66
+ i0.ɵɵtext(2);
32
67
  i0.ɵɵelementEnd();
68
+ } if (rf & 2) {
69
+ const component_r5 = i0.ɵɵnextContext().$implicit;
70
+ const ctx_r2 = i0.ɵɵnextContext(2);
71
+ i0.ɵɵpropertyInterpolate1("title", "Loaded from ", ctx_r2.getComponentFilename(component_r5), "");
72
+ i0.ɵɵadvance(2);
73
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getComponentFilename(component_r5), " ");
33
74
  } }
34
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
35
- i0.ɵɵelementStart(0, "span", 30);
75
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
76
+ i0.ɵɵelementStart(0, "span", 43);
77
+ i0.ɵɵtext(1, "File");
78
+ i0.ɵɵelementEnd();
79
+ } }
80
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
81
+ i0.ɵɵelementStart(0, "span", 44);
36
82
  i0.ɵɵtext(1, "Published");
37
83
  i0.ɵɵelementEnd();
38
84
  } }
39
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
40
- i0.ɵɵelementStart(0, "span", 31);
85
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_15_Template(rf, ctx) { if (rf & 1) {
86
+ i0.ɵɵelementStart(0, "span", 45);
41
87
  i0.ɵɵtext(1, "Draft");
42
88
  i0.ɵɵelementEnd();
43
89
  } }
44
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_15_Template(rf, ctx) { if (rf & 1) {
45
- i0.ɵɵelement(0, "i", 33);
90
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_17_Template(rf, ctx) { if (rf & 1) {
91
+ i0.ɵɵelement(0, "i", 47);
46
92
  } }
47
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_16_Template(rf, ctx) { if (rf & 1) {
48
- i0.ɵɵelement(0, "i", 34);
93
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_18_Template(rf, ctx) { if (rf & 1) {
94
+ i0.ɵɵelement(0, "i", 48);
49
95
  } }
50
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_1_Template(rf, ctx) { if (rf & 1) {
51
- i0.ɵɵelementStart(0, "div", 36)(1, "label");
96
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
97
+ i0.ɵɵelementStart(0, "div", 51)(1, "label");
52
98
  i0.ɵɵtext(2, "Description");
53
99
  i0.ɵɵelementEnd();
54
100
  i0.ɵɵelementStart(3, "p");
55
101
  i0.ɵɵtext(4);
56
102
  i0.ɵɵelementEnd()();
57
103
  } if (rf & 2) {
58
- const component_r2 = i0.ɵɵnextContext(2).$implicit;
104
+ const component_r5 = i0.ɵɵnextContext(2).$implicit;
105
+ const ctx_r2 = i0.ɵɵnextContext(2);
59
106
  i0.ɵɵadvance(4);
60
- i0.ɵɵtextInterpolate(component_r2.Description);
107
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentDescription(component_r5));
61
108
  } }
62
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_21_Template(rf, ctx) { if (rf & 1) {
63
- i0.ɵɵelementStart(0, "div", 38)(1, "span", 39);
109
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_21_Template(rf, ctx) { if (rf & 1) {
110
+ i0.ɵɵelementStart(0, "div", 53)(1, "span", 54);
111
+ i0.ɵɵtext(2, "Loaded:");
112
+ i0.ɵɵelementEnd();
113
+ i0.ɵɵelementStart(3, "span", 55);
114
+ i0.ɵɵtext(4);
115
+ i0.ɵɵpipe(5, "date");
116
+ i0.ɵɵelementEnd()();
117
+ } if (rf & 2) {
118
+ const component_r5 = i0.ɵɵnextContext(2).$implicit;
119
+ const ctx_r2 = i0.ɵɵnextContext(2);
120
+ i0.ɵɵadvance(4);
121
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, ctx_r2.getComponentLoadedAt(component_r5), "short"));
122
+ } }
123
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_22_Template(rf, ctx) { if (rf & 1) {
124
+ i0.ɵɵelementStart(0, "div", 53)(1, "span", 54);
64
125
  i0.ɵɵtext(2, "Updated:");
65
126
  i0.ɵɵelementEnd();
66
- i0.ɵɵelementStart(3, "span", 40);
127
+ i0.ɵɵelementStart(3, "span", 55);
67
128
  i0.ɵɵtext(4);
68
129
  i0.ɵɵpipe(5, "date");
69
130
  i0.ɵɵelementEnd()();
70
131
  } if (rf & 2) {
71
- const component_r2 = i0.ɵɵnextContext(2).$implicit;
132
+ const component_r5 = i0.ɵɵnextContext(2).$implicit;
133
+ const ctx_r2 = i0.ɵɵnextContext(2);
72
134
  i0.ɵɵadvance(4);
73
- i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, component_r2.__mj_UpdatedAt, "short"));
135
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, ctx_r2.getComponentUpdatedAt(component_r5), "short"));
74
136
  } }
75
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_23_Template(rf, ctx) { if (rf & 1) {
76
- const _r4 = i0.ɵɵgetCurrentView();
77
- i0.ɵɵelementStart(0, "button", 43);
78
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_23_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.stopComponent(); return i0.ɵɵresetView($event.stopPropagation()); });
79
- i0.ɵɵtext(1, " Stop Component ");
137
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_24_Template(rf, ctx) { if (rf & 1) {
138
+ const _r6 = i0.ɵɵgetCurrentView();
139
+ i0.ɵɵelementStart(0, "button", 8);
140
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_24_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(4); ctx_r2.stopComponent(); return i0.ɵɵresetView($event.stopPropagation()); });
141
+ i0.ɵɵelement(1, "span", 58);
142
+ i0.ɵɵtext(2, " Stop Component ");
80
143
  i0.ɵɵelementEnd();
81
144
  } if (rf & 2) {
82
- i0.ɵɵproperty("icon", "fa-solid fa-stop")("themeColor", "error");
145
+ i0.ɵɵproperty("themeColor", "error");
83
146
  } }
84
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_24_Template(rf, ctx) { if (rf & 1) {
85
- const _r5 = i0.ɵɵgetCurrentView();
86
- i0.ɵɵelementStart(0, "button", 43);
87
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_24_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const component_r2 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r2); return i0.ɵɵresetView($event.stopPropagation()); });
88
- i0.ɵɵtext(1, " Run Component ");
147
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_25_Template(rf, ctx) { if (rf & 1) {
148
+ const _r7 = i0.ɵɵgetCurrentView();
149
+ i0.ɵɵelementStart(0, "button", 59);
150
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_25_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r7); const component_r5 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r5); return i0.ɵɵresetView($event.stopPropagation()); });
151
+ i0.ɵɵelement(1, "span", 60);
152
+ i0.ɵɵtext(2, " Switch to This Component ");
153
+ i0.ɵɵelementEnd();
154
+ } if (rf & 2) {
155
+ i0.ɵɵproperty("themeColor", "base");
156
+ } }
157
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_26_Template(rf, ctx) { if (rf & 1) {
158
+ const _r8 = i0.ɵɵgetCurrentView();
159
+ i0.ɵɵelementStart(0, "button", 8);
160
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_26_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r8); const component_r5 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.runComponent(component_r5); return i0.ɵɵresetView($event.stopPropagation()); });
161
+ i0.ɵɵelement(1, "span", 60);
162
+ i0.ɵɵtext(2, " Run Component ");
89
163
  i0.ɵɵelementEnd();
90
164
  } if (rf & 2) {
91
- i0.ɵɵproperty("icon", "fa-solid fa-play")("themeColor", "primary");
165
+ i0.ɵɵproperty("themeColor", "primary");
92
166
  } }
93
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Template(rf, ctx) { if (rf & 1) {
94
- i0.ɵɵelementStart(0, "div", 35);
95
- i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_1_Template, 5, 1, "div", 36);
96
- i0.ɵɵelementStart(2, "div", 36)(3, "label");
167
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Template(rf, ctx) { if (rf & 1) {
168
+ i0.ɵɵelementStart(0, "div", 49);
169
+ i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_1_Template, 5, 1, "div", 51);
170
+ i0.ɵɵelementStart(2, "div", 51)(3, "label");
97
171
  i0.ɵɵtext(4, "Component Info");
98
172
  i0.ɵɵelementEnd();
99
- i0.ɵɵelementStart(5, "div", 37)(6, "div", 38)(7, "span", 39);
173
+ i0.ɵɵelementStart(5, "div", 52)(6, "div", 53)(7, "span", 54);
100
174
  i0.ɵɵtext(8, "Type:");
101
175
  i0.ɵɵelementEnd();
102
- i0.ɵɵelementStart(9, "span", 40);
176
+ i0.ɵɵelementStart(9, "span", 55);
103
177
  i0.ɵɵtext(10);
104
178
  i0.ɵɵelementEnd()();
105
- i0.ɵɵelementStart(11, "div", 38)(12, "span", 39);
179
+ i0.ɵɵelementStart(11, "div", 53)(12, "span", 54);
106
180
  i0.ɵɵtext(13, "Version:");
107
181
  i0.ɵɵelementEnd();
108
- i0.ɵɵelementStart(14, "span", 40);
182
+ i0.ɵɵelementStart(14, "span", 55);
109
183
  i0.ɵɵtext(15);
110
184
  i0.ɵɵelementEnd()();
111
- i0.ɵɵelementStart(16, "div", 38)(17, "span", 39);
185
+ i0.ɵɵelementStart(16, "div", 53)(17, "span", 54);
112
186
  i0.ɵɵtext(18, "Status:");
113
187
  i0.ɵɵelementEnd();
114
- i0.ɵɵelementStart(19, "span", 40);
188
+ i0.ɵɵelementStart(19, "span", 55);
115
189
  i0.ɵɵtext(20);
116
190
  i0.ɵɵelementEnd()();
117
- i0.ɵɵtemplate(21, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_21_Template, 6, 4, "div", 38);
191
+ i0.ɵɵtemplate(21, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_21_Template, 6, 4, "div", 53)(22, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_22_Template, 6, 4, "div", 53);
118
192
  i0.ɵɵelementEnd()();
119
- i0.ɵɵelementStart(22, "div", 41);
120
- i0.ɵɵtemplate(23, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_23_Template, 2, 2, "button", 42)(24, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Conditional_24_Template, 2, 2, "button", 42);
193
+ i0.ɵɵelementStart(23, "div", 56);
194
+ i0.ɵɵtemplate(24, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_24_Template, 3, 1, "button", 7)(25, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_25_Template, 3, 1, "button", 57)(26, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Conditional_26_Template, 3, 1, "button", 7);
121
195
  i0.ɵɵelementEnd()();
122
196
  } if (rf & 2) {
123
- const component_r2 = i0.ɵɵnextContext().$implicit;
197
+ const component_r5 = i0.ɵɵnextContext().$implicit;
124
198
  const ctx_r2 = i0.ɵɵnextContext(2);
125
199
  i0.ɵɵadvance();
126
- i0.ɵɵconditional(component_r2.Description ? 1 : -1);
200
+ i0.ɵɵconditional(ctx_r2.getComponentDescription(component_r5) ? 1 : -1);
127
201
  i0.ɵɵadvance(9);
128
- i0.ɵɵtextInterpolate(component_r2.Type || "Unknown");
202
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentType(component_r5) || "Unknown");
129
203
  i0.ɵɵadvance(5);
130
- i0.ɵɵtextInterpolate(component_r2.Version || "1.0.0");
204
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentVersion(component_r5));
131
205
  i0.ɵɵadvance(5);
132
- i0.ɵɵtextInterpolate(component_r2.Status || "Draft");
206
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentStatus(component_r5) || "Draft");
133
207
  i0.ɵɵadvance();
134
- i0.ɵɵconditional(component_r2.__mj_UpdatedAt ? 21 : -1);
135
- i0.ɵɵadvance(2);
136
- i0.ɵɵconditional((ctx_r2.selectedComponent == null ? null : ctx_r2.selectedComponent.ID) === component_r2.ID && ctx_r2.isRunning ? 23 : 24);
208
+ i0.ɵɵconditional(ctx_r2.isFileLoadedComponent(component_r5) ? 21 : !ctx_r2.isFileLoadedComponent(component_r5) && ctx_r2.getComponentUpdatedAt(component_r5) ? 22 : -1);
209
+ i0.ɵɵadvance(3);
210
+ i0.ɵɵconditional(ctx_r2.selectedComponent && ctx_r2.getComponentId(ctx_r2.selectedComponent) === ctx_r2.getComponentId(component_r5) && ctx_r2.isRunning ? 24 : ctx_r2.isRunning && ctx_r2.selectedComponent && ctx_r2.getComponentId(ctx_r2.selectedComponent) !== ctx_r2.getComponentId(component_r5) ? 25 : 26);
137
211
  } }
138
- function ComponentStudioDashboardComponent_Conditional_20_For_1_Template(rf, ctx) { if (rf & 1) {
139
- const _r1 = i0.ɵɵgetCurrentView();
140
- i0.ɵɵelementStart(0, "div", 21)(1, "div", 22);
141
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_20_For_1_Template_div_click_1_listener() { const component_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleComponentExpansion(component_r2)); });
142
- i0.ɵɵelementStart(2, "div", 23);
143
- i0.ɵɵelement(3, "i", 24);
212
+ function ComponentStudioDashboardComponent_Conditional_31_For_1_Template(rf, ctx) { if (rf & 1) {
213
+ const _r4 = i0.ɵɵgetCurrentView();
214
+ i0.ɵɵelementStart(0, "div", 33)(1, "div", 34);
215
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_31_For_1_Template_div_click_1_listener() { const component_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleComponentExpansion(component_r5)); });
216
+ i0.ɵɵelementStart(2, "div", 35);
217
+ i0.ɵɵelement(3, "i", 36);
144
218
  i0.ɵɵelementEnd();
145
- i0.ɵɵelementStart(4, "div", 25)(5, "div", 26);
219
+ i0.ɵɵelementStart(4, "div", 37)(5, "div", 38);
146
220
  i0.ɵɵtext(6);
221
+ i0.ɵɵtemplate(7, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_7_Template, 3, 3, "span", 39);
147
222
  i0.ɵɵelementEnd();
148
- i0.ɵɵelementStart(7, "div", 27)(8, "span", 28);
149
- i0.ɵɵtext(9);
223
+ i0.ɵɵelementStart(8, "div", 40)(9, "span", 41);
224
+ i0.ɵɵtext(10);
150
225
  i0.ɵɵelementEnd();
151
- i0.ɵɵelementStart(10, "span", 29);
152
- i0.ɵɵtext(11);
226
+ i0.ɵɵelementStart(11, "span", 42);
227
+ i0.ɵɵtext(12);
153
228
  i0.ɵɵelementEnd();
154
- i0.ɵɵtemplate(12, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_12_Template, 2, 0, "span", 30)(13, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_13_Template, 2, 0, "span", 31);
229
+ i0.ɵɵtemplate(13, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_13_Template, 2, 0, "span", 43)(14, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_14_Template, 2, 0, "span", 44)(15, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_15_Template, 2, 0, "span", 45);
155
230
  i0.ɵɵelementEnd()();
156
- i0.ɵɵelementStart(14, "div", 32);
157
- i0.ɵɵtemplate(15, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_15_Template, 1, 0, "i", 33)(16, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_16_Template, 1, 0, "i", 34);
231
+ i0.ɵɵelementStart(16, "div", 46);
232
+ i0.ɵɵtemplate(17, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_17_Template, 1, 0, "i", 47)(18, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_18_Template, 1, 0, "i", 48);
158
233
  i0.ɵɵelementEnd()();
159
- i0.ɵɵtemplate(17, ComponentStudioDashboardComponent_Conditional_20_For_1_Conditional_17_Template, 25, 6, "div", 35);
234
+ i0.ɵɵtemplate(19, ComponentStudioDashboardComponent_Conditional_31_For_1_Conditional_19_Template, 27, 6, "div", 49);
160
235
  i0.ɵɵelementEnd();
161
236
  } if (rf & 2) {
162
- const component_r2 = ctx.$implicit;
237
+ const component_r5 = ctx.$implicit;
163
238
  const ctx_r2 = i0.ɵɵnextContext(2);
164
- i0.ɵɵclassProp("expanded", (ctx_r2.expandedComponent == null ? null : ctx_r2.expandedComponent.ID) === component_r2.ID)("running", (ctx_r2.selectedComponent == null ? null : ctx_r2.selectedComponent.ID) === component_r2.ID && ctx_r2.isRunning);
239
+ i0.ɵɵclassProp("expanded", ctx_r2.expandedComponent && ctx_r2.getComponentId(ctx_r2.expandedComponent) === ctx_r2.getComponentId(component_r5))("running", ctx_r2.selectedComponent && ctx_r2.getComponentId(ctx_r2.selectedComponent) === ctx_r2.getComponentId(component_r5) && ctx_r2.isRunning)("file-loaded", ctx_r2.isFileLoadedComponent(component_r5));
165
240
  i0.ɵɵadvance(2);
166
- i0.ɵɵstyleProp("color", ctx_r2.getComponentTypeColor(component_r2.Type));
241
+ i0.ɵɵstyleProp("color", ctx_r2.getComponentTypeColor(ctx_r2.getComponentType(component_r5)));
167
242
  i0.ɵɵadvance();
168
- i0.ɵɵproperty("ngClass", ctx_r2.getComponentTypeIcon(component_r2.Type));
243
+ i0.ɵɵproperty("ngClass", ctx_r2.getComponentTypeIcon(ctx_r2.getComponentType(component_r5)));
169
244
  i0.ɵɵadvance(3);
170
- i0.ɵɵtextInterpolate(component_r2.Name);
245
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getComponentName(component_r5), " ");
246
+ i0.ɵɵadvance();
247
+ i0.ɵɵconditional(ctx_r2.isFileLoadedComponent(component_r5) ? 7 : -1);
171
248
  i0.ɵɵadvance(3);
172
- i0.ɵɵtextInterpolate(component_r2.Type || "Component");
249
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentType(component_r5) || "Component");
173
250
  i0.ɵɵadvance(2);
174
- i0.ɵɵtextInterpolate1("v", component_r2.Version || "1.0.0", "");
251
+ i0.ɵɵtextInterpolate1("v", ctx_r2.getComponentVersion(component_r5), "");
175
252
  i0.ɵɵadvance();
176
- i0.ɵɵconditional(component_r2.Status === "Published" ? 12 : 13);
177
- i0.ɵɵadvance(3);
178
- i0.ɵɵconditional((ctx_r2.expandedComponent == null ? null : ctx_r2.expandedComponent.ID) === component_r2.ID ? 15 : 16);
253
+ i0.ɵɵconditional(ctx_r2.isFileLoadedComponent(component_r5) ? 13 : ctx_r2.getComponentStatus(component_r5) === "Published" ? 14 : 15);
254
+ i0.ɵɵadvance(4);
255
+ i0.ɵɵconditional(ctx_r2.expandedComponent && ctx_r2.getComponentId(ctx_r2.expandedComponent) === ctx_r2.getComponentId(component_r5) ? 17 : 18);
179
256
  i0.ɵɵadvance(2);
180
- i0.ɵɵconditional((ctx_r2.expandedComponent == null ? null : ctx_r2.expandedComponent.ID) === component_r2.ID ? 17 : -1);
257
+ i0.ɵɵconditional(ctx_r2.expandedComponent && ctx_r2.getComponentId(ctx_r2.expandedComponent) === ctx_r2.getComponentId(component_r5) ? 19 : -1);
181
258
  } }
182
- function ComponentStudioDashboardComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
183
- i0.ɵɵrepeaterCreate(0, ComponentStudioDashboardComponent_Conditional_20_For_1_Template, 18, 13, "div", 20, _forTrack0);
259
+ function ComponentStudioDashboardComponent_Conditional_31_Template(rf, ctx) { if (rf & 1) {
260
+ i0.ɵɵrepeaterCreate(0, ComponentStudioDashboardComponent_Conditional_31_For_1_Template, 20, 16, "div", 32, _forTrack0, true);
184
261
  } if (rf & 2) {
185
262
  const ctx_r2 = i0.ɵɵnextContext();
186
263
  i0.ɵɵrepeater(ctx_r2.filteredComponents);
187
264
  } }
188
- function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Conditional_18_Template(rf, ctx) { if (rf & 1) {
189
- i0.ɵɵelementStart(0, "details", 53)(1, "summary");
265
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Conditional_18_Template(rf, ctx) { if (rf & 1) {
266
+ i0.ɵɵelementStart(0, "details", 77)(1, "summary");
190
267
  i0.ɵɵtext(2, "Technical Details (click to expand)");
191
268
  i0.ɵɵelementEnd();
192
269
  i0.ɵɵelementStart(3, "pre");
193
270
  i0.ɵɵtext(4);
194
271
  i0.ɵɵelementEnd()();
195
272
  } if (rf & 2) {
196
- const ctx_r2 = i0.ɵɵnextContext(3);
273
+ const ctx_r2 = i0.ɵɵnextContext(4);
197
274
  i0.ɵɵadvance(4);
198
275
  i0.ɵɵtextInterpolate(ctx_r2.formatTechnicalDetails(ctx_r2.currentError.technicalDetails));
199
276
  } }
200
- function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template(rf, ctx) { if (rf & 1) {
201
- const _r6 = i0.ɵɵgetCurrentView();
202
- i0.ɵɵelementStart(0, "div", 44)(1, "div", 46)(2, "div", 47);
203
- i0.ɵɵelement(3, "i", 48);
277
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
278
+ const _r10 = i0.ɵɵgetCurrentView();
279
+ i0.ɵɵelementStart(0, "div", 68)(1, "div", 70)(2, "div", 71);
280
+ i0.ɵɵelement(3, "i", 72);
204
281
  i0.ɵɵelementStart(4, "h3");
205
282
  i0.ɵɵtext(5, "Component Error");
206
283
  i0.ɵɵelementEnd();
207
- i0.ɵɵelementStart(6, "button", 49);
208
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.copyErrorToClipboard()); });
209
- i0.ɵɵelement(7, "i", 50);
284
+ i0.ɵɵelementStart(6, "button", 73);
285
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.copyErrorToClipboard()); });
286
+ i0.ɵɵelement(7, "i", 74);
210
287
  i0.ɵɵelementEnd()();
211
- i0.ɵɵelementStart(8, "p", 51);
288
+ i0.ɵɵelementStart(8, "p", 75);
212
289
  i0.ɵɵtext(9, " The component could not be rendered due to the following error: ");
213
290
  i0.ɵɵelementEnd();
214
- i0.ɵɵelementStart(10, "div", 52)(11, "strong");
291
+ i0.ɵɵelementStart(10, "div", 76)(11, "strong");
215
292
  i0.ɵɵtext(12, "Error Type:");
216
293
  i0.ɵɵelementEnd();
217
294
  i0.ɵɵtext(13);
@@ -220,9 +297,9 @@ function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template
220
297
  i0.ɵɵtext(16, "Message:");
221
298
  i0.ɵɵelementEnd();
222
299
  i0.ɵɵtext(17);
223
- i0.ɵɵtemplate(18, ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Conditional_18_Template, 5, 1, "details", 53);
300
+ i0.ɵɵtemplate(18, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Conditional_18_Template, 5, 1, "details", 77);
224
301
  i0.ɵɵelementEnd();
225
- i0.ɵɵelementStart(19, "div", 54)(20, "strong");
302
+ i0.ɵɵelementStart(19, "div", 78)(20, "strong");
226
303
  i0.ɵɵtext(21, "What to do:");
227
304
  i0.ɵɵelementEnd();
228
305
  i0.ɵɵelementStart(22, "ol")(23, "li");
@@ -237,56 +314,218 @@ function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template
237
314
  i0.ɵɵelementStart(29, "li");
238
315
  i0.ɵɵtext(30, "Contact your system administrator if the issue persists");
239
316
  i0.ɵɵelementEnd()()();
240
- i0.ɵɵelementStart(31, "div", 55)(32, "button", 56);
241
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.retryComponent()); });
242
- i0.ɵɵtext(33, " Retry ");
317
+ i0.ɵɵelementStart(31, "div", 79)(32, "button", 80);
318
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template_button_click_32_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.retryComponent()); });
319
+ i0.ɵɵelement(33, "span", 81);
320
+ i0.ɵɵtext(34, " Retry ");
243
321
  i0.ɵɵelementEnd();
244
- i0.ɵɵelementStart(34, "button", 43);
245
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template_button_click_34_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.stopComponent()); });
246
- i0.ɵɵtext(35, " Stop ");
322
+ i0.ɵɵelementStart(35, "button", 8);
323
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template_button_click_35_listener() { i0.ɵɵrestoreView(_r10); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.stopComponent()); });
324
+ i0.ɵɵelement(36, "span", 58);
325
+ i0.ɵɵtext(37, " Stop ");
247
326
  i0.ɵɵelementEnd()()()();
248
327
  } if (rf & 2) {
249
- const ctx_r2 = i0.ɵɵnextContext(2);
328
+ const ctx_r2 = i0.ɵɵnextContext(3);
250
329
  i0.ɵɵadvance(13);
251
330
  i0.ɵɵtextInterpolate1(" ", ctx_r2.currentError.type, "");
252
331
  i0.ɵɵadvance(4);
253
332
  i0.ɵɵtextInterpolate1(" ", ctx_r2.currentError.message, " ");
254
333
  i0.ɵɵadvance();
255
334
  i0.ɵɵconditional(ctx_r2.currentError.technicalDetails ? 18 : -1);
256
- i0.ɵɵadvance(14);
257
- i0.ɵɵproperty("icon", "fa-solid fa-rotate");
335
+ i0.ɵɵadvance(17);
336
+ i0.ɵɵproperty("themeColor", "error");
337
+ } }
338
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
339
+ const _r11 = i0.ɵɵgetCurrentView();
340
+ i0.ɵɵelementStart(0, "mj-react-component", 82);
341
+ i0.ɵɵlistener("componentEvent", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template_mj_react_component_componentEvent_0_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onComponentEvent($event)); })("openEntityRecord", function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template_mj_react_component_openEntityRecord_0_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onOpenEntityRecord($event)); });
342
+ i0.ɵɵelementEnd();
343
+ } if (rf & 2) {
344
+ const ctx_r2 = i0.ɵɵnextContext(3);
345
+ i0.ɵɵproperty("component", ctx_r2.componentSpec);
346
+ } }
347
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Template(rf, ctx) { if (rf & 1) {
348
+ i0.ɵɵtemplate(0, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_0_Template, 38, 4, "div", 68)(1, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Conditional_1_Template, 1, 1, "mj-react-component", 69);
349
+ } if (rf & 2) {
350
+ const ctx_r2 = i0.ɵɵnextContext(2);
351
+ i0.ɵɵconditional(ctx_r2.currentError ? 0 : 1);
352
+ } }
353
+ function ComponentStudioDashboardComponent_Conditional_34_Conditional_4_Template(rf, ctx) { if (rf & 1) {
354
+ const _r12 = i0.ɵɵgetCurrentView();
355
+ i0.ɵɵelementStart(0, "div", 63);
356
+ i0.ɵɵelement(1, "i", 83);
357
+ i0.ɵɵelementStart(2, "h3");
358
+ i0.ɵɵtext(3);
359
+ i0.ɵɵelementEnd();
360
+ i0.ɵɵelementStart(4, "p");
361
+ i0.ɵɵtext(5);
362
+ i0.ɵɵelementEnd();
363
+ i0.ɵɵelementStart(6, "button", 84);
364
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_Conditional_4_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r12); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.runComponent(ctx_r2.selectedComponent)); });
365
+ i0.ɵɵelement(7, "span", 60);
366
+ i0.ɵɵtext(8, " Run Component ");
367
+ i0.ɵɵelementEnd()();
368
+ } if (rf & 2) {
369
+ const ctx_r2 = i0.ɵɵnextContext(2);
370
+ i0.ɵɵadvance(3);
371
+ i0.ɵɵtextInterpolate1("Component: ", ctx_r2.getComponentName(ctx_r2.selectedComponent), "");
258
372
  i0.ɵɵadvance(2);
259
- i0.ɵɵproperty("icon", "fa-solid fa-stop")("themeColor", "error");
373
+ i0.ɵɵtextInterpolate(ctx_r2.getComponentDescription(ctx_r2.selectedComponent) || "No description available");
374
+ i0.ɵɵadvance();
375
+ i0.ɵɵproperty("themeColor", "primary")("size", "large");
260
376
  } }
261
- function ComponentStudioDashboardComponent_Conditional_23_Conditional_1_Template(rf, ctx) { if (rf & 1) {
262
- const _r7 = i0.ɵɵgetCurrentView();
263
- i0.ɵɵelementStart(0, "mj-react-component", 57);
264
- i0.ɵɵlistener("componentEvent", function ComponentStudioDashboardComponent_Conditional_23_Conditional_1_Template_mj_react_component_componentEvent_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onComponentEvent($event)); })("openEntityRecord", function ComponentStudioDashboardComponent_Conditional_23_Conditional_1_Template_mj_react_component_openEntityRecord_0_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onOpenEntityRecord($event)); });
377
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template(rf, ctx) { if (rf & 1) {
378
+ const _r14 = i0.ɵɵgetCurrentView();
379
+ i0.ɵɵelementStart(0, "button", 8);
380
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.applySpecChanges()); });
381
+ i0.ɵɵelement(1, "span", 91);
382
+ i0.ɵɵtext(2, " Apply Changes ");
383
+ i0.ɵɵelementEnd();
384
+ i0.ɵɵelementStart(3, "button", 80);
385
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.initializeEditors()); });
386
+ i0.ɵɵelement(4, "span", 92);
387
+ i0.ɵɵtext(5, " Cancel ");
388
+ i0.ɵɵelementEnd();
389
+ } if (rf & 2) {
390
+ i0.ɵɵproperty("themeColor", "primary");
391
+ } }
392
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_7_Template(rf, ctx) { if (rf & 1) {
393
+ const _r15 = i0.ɵɵgetCurrentView();
394
+ i0.ɵɵelementStart(0, "button", 8);
395
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.refreshComponent()); });
396
+ i0.ɵɵelement(1, "span", 11);
397
+ i0.ɵɵtext(2, " Refresh Component ");
398
+ i0.ɵɵelementEnd();
399
+ } if (rf & 2) {
400
+ i0.ɵɵproperty("themeColor", "info");
401
+ } }
402
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template(rf, ctx) { if (rf & 1) {
403
+ const _r13 = i0.ɵɵgetCurrentView();
404
+ i0.ɵɵelementStart(0, "div", 85)(1, "div", 86)(2, "h4");
405
+ i0.ɵɵelement(3, "i", 87);
406
+ i0.ɵɵtext(4, " Component Specification (JSON)");
265
407
  i0.ɵɵelementEnd();
408
+ i0.ɵɵelementStart(5, "div", 88);
409
+ i0.ɵɵtemplate(6, ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_6_Template, 6, 1)(7, ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Conditional_7_Template, 3, 1, "button", 7);
410
+ i0.ɵɵelementEnd()();
411
+ i0.ɵɵelementStart(8, "div", 89)(9, "mj-code-editor", 90);
412
+ i0.ɵɵtwoWayListener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template_mj_code_editor_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r2.editableSpec, $event) || (ctx_r2.editableSpec = $event); return i0.ɵɵresetView($event); });
413
+ i0.ɵɵlistener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template_mj_code_editor_ngModelChange_9_listener($event) { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onSpecChange($event)); });
414
+ i0.ɵɵelementEnd()()();
266
415
  } if (rf & 2) {
267
416
  const ctx_r2 = i0.ɵɵnextContext(2);
268
- i0.ɵɵproperty("component", ctx_r2.componentSpec);
417
+ i0.ɵɵadvance(6);
418
+ i0.ɵɵconditional(ctx_r2.isEditingSpec ? 6 : -1);
419
+ i0.ɵɵadvance();
420
+ i0.ɵɵconditional(ctx_r2.isRunning ? 7 : -1);
421
+ i0.ɵɵadvance(2);
422
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r2.editableSpec);
423
+ i0.ɵɵproperty("language", "json")("readonly", false);
424
+ } }
425
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template(rf, ctx) { if (rf & 1) {
426
+ const _r16 = i0.ɵɵgetCurrentView();
427
+ i0.ɵɵelementStart(0, "button", 8);
428
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.applyCodeChanges()); });
429
+ i0.ɵɵelement(1, "span", 91);
430
+ i0.ɵɵtext(2, " Apply Changes ");
431
+ i0.ɵɵelementEnd();
432
+ i0.ɵɵelementStart(3, "button", 80);
433
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.initializeEditors()); });
434
+ i0.ɵɵelement(4, "span", 92);
435
+ i0.ɵɵtext(5, " Cancel ");
436
+ i0.ɵɵelementEnd();
437
+ } if (rf & 2) {
438
+ i0.ɵɵproperty("themeColor", "primary");
439
+ } }
440
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_7_Template(rf, ctx) { if (rf & 1) {
441
+ const _r17 = i0.ɵɵgetCurrentView();
442
+ i0.ɵɵelementStart(0, "button", 8);
443
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.refreshComponent()); });
444
+ i0.ɵɵelement(1, "span", 11);
445
+ i0.ɵɵtext(2, " Refresh Component ");
446
+ i0.ɵɵelementEnd();
447
+ } if (rf & 2) {
448
+ i0.ɵɵproperty("themeColor", "info");
449
+ } }
450
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_ng_template_1_Template(rf, ctx) { if (rf & 1) {
451
+ const _r18 = i0.ɵɵgetCurrentView();
452
+ i0.ɵɵelementStart(0, "mj-code-editor", 98);
453
+ i0.ɵɵlistener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_ng_template_1_Template_mj_code_editor_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r18); const ɵ$index_390_r19 = i0.ɵɵnextContext().$index; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onCodeSectionChange($event, ɵ$index_390_r19)); });
454
+ i0.ɵɵelementEnd();
455
+ } if (rf & 2) {
456
+ const section_r20 = i0.ɵɵnextContext().$implicit;
457
+ i0.ɵɵproperty("ngModel", section_r20.code)("language", "javascript")("readonly", false);
458
+ } }
459
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_Template(rf, ctx) { if (rf & 1) {
460
+ i0.ɵɵelementStart(0, "kendo-panelbar-item", 96);
461
+ i0.ɵɵtemplate(1, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_ng_template_1_Template, 1, 3, "ng-template", 97);
462
+ i0.ɵɵelementEnd();
463
+ } if (rf & 2) {
464
+ const section_r20 = ctx.$implicit;
465
+ i0.ɵɵproperty("title", section_r20.title)("expanded", section_r20.expanded);
466
+ } }
467
+ function ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Template(rf, ctx) { if (rf & 1) {
468
+ i0.ɵɵelementStart(0, "div", 93)(1, "div", 86)(2, "h4");
469
+ i0.ɵɵelement(3, "i", 94);
470
+ i0.ɵɵtext(4, " Component Code (JavaScript/React)");
471
+ i0.ɵɵelementEnd();
472
+ i0.ɵɵelementStart(5, "div", 88);
473
+ i0.ɵɵtemplate(6, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_6_Template, 6, 1)(7, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Conditional_7_Template, 3, 1, "button", 7);
474
+ i0.ɵɵelementEnd()();
475
+ i0.ɵɵelementStart(8, "div", 89)(9, "kendo-panelbar", 95);
476
+ i0.ɵɵrepeaterCreate(10, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_For_11_Template, 2, 2, "kendo-panelbar-item", 96, _forTrack1);
477
+ i0.ɵɵelementEnd()()();
478
+ } if (rf & 2) {
479
+ const ctx_r2 = i0.ɵɵnextContext(2);
480
+ i0.ɵɵadvance(6);
481
+ i0.ɵɵconditional(ctx_r2.isEditingCode ? 6 : -1);
482
+ i0.ɵɵadvance();
483
+ i0.ɵɵconditional(ctx_r2.isRunning ? 7 : -1);
484
+ i0.ɵɵadvance(3);
485
+ i0.ɵɵrepeater(ctx_r2.getComponentCodeSections());
269
486
  } }
270
- function ComponentStudioDashboardComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
271
- i0.ɵɵtemplate(0, ComponentStudioDashboardComponent_Conditional_23_Conditional_0_Template, 36, 6, "div", 44)(1, ComponentStudioDashboardComponent_Conditional_23_Conditional_1_Template, 1, 1, "mj-react-component", 45);
487
+ function ComponentStudioDashboardComponent_Conditional_34_Template(rf, ctx) { if (rf & 1) {
488
+ const _r9 = i0.ɵɵgetCurrentView();
489
+ i0.ɵɵelementStart(0, "kendo-splitter", 25)(1, "kendo-splitter-pane", 61)(2, "div", 62);
490
+ i0.ɵɵtemplate(3, ComponentStudioDashboardComponent_Conditional_34_Conditional_3_Template, 2, 1)(4, ComponentStudioDashboardComponent_Conditional_34_Conditional_4_Template, 9, 4, "div", 63);
491
+ i0.ɵɵelementEnd()();
492
+ i0.ɵɵelementStart(5, "kendo-splitter-pane", 64)(6, "kendo-tabstrip", 65);
493
+ i0.ɵɵlistener("tabSelect", function ComponentStudioDashboardComponent_Conditional_34_Template_kendo_tabstrip_tabSelect_6_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onTabSelect($event)); });
494
+ i0.ɵɵelementStart(7, "kendo-tabstrip-tab", 66);
495
+ i0.ɵɵtemplate(8, ComponentStudioDashboardComponent_Conditional_34_ng_template_8_Template, 10, 5, "ng-template", 67);
496
+ i0.ɵɵelementEnd();
497
+ i0.ɵɵelementStart(9, "kendo-tabstrip-tab", 66);
498
+ i0.ɵɵtemplate(10, ComponentStudioDashboardComponent_Conditional_34_ng_template_10_Template, 12, 2, "ng-template", 67);
499
+ i0.ɵɵelementEnd()()()();
272
500
  } if (rf & 2) {
273
501
  const ctx_r2 = i0.ɵɵnextContext();
274
- i0.ɵɵconditional(ctx_r2.currentError ? 0 : 1);
502
+ i0.ɵɵadvance();
503
+ i0.ɵɵproperty("min", "300px")("collapsible", false)("size", ctx_r2.isDetailsPaneCollapsed ? "100%" : "50%");
504
+ i0.ɵɵadvance(2);
505
+ i0.ɵɵconditional(ctx_r2.isRunning && ctx_r2.componentSpec ? 3 : 4);
506
+ i0.ɵɵadvance(2);
507
+ i0.ɵɵproperty("min", "400px")("collapsible", true)("collapsed", ctx_r2.isDetailsPaneCollapsed);
508
+ i0.ɵɵadvance(2);
509
+ i0.ɵɵproperty("title", "Spec")("selected", ctx_r2.activeTab === 0);
510
+ i0.ɵɵadvance(2);
511
+ i0.ɵɵproperty("title", "Code")("selected", ctx_r2.activeTab === 1);
275
512
  } }
276
- function ComponentStudioDashboardComponent_Conditional_24_Template(rf, ctx) { if (rf & 1) {
277
- i0.ɵɵelementStart(0, "div", 17);
278
- i0.ɵɵelement(1, "i", 58);
513
+ function ComponentStudioDashboardComponent_Conditional_35_Template(rf, ctx) { if (rf & 1) {
514
+ i0.ɵɵelementStart(0, "div", 26);
515
+ i0.ɵɵelement(1, "i", 99);
279
516
  i0.ɵɵelementStart(2, "h2");
280
517
  i0.ɵɵtext(3, "Ready to Test Components");
281
518
  i0.ɵɵelementEnd();
282
519
  i0.ɵɵelementStart(4, "p");
283
- i0.ɵɵtext(5, "Select a component from the list and click \"Run Component\" to see it in action");
520
+ i0.ɵɵtext(5, "Select a component from the list to view its details and run it");
284
521
  i0.ɵɵelementEnd()();
285
522
  } }
286
523
  let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent extends BaseDashboard {
287
524
  cdr;
288
525
  // Component data
289
526
  components = [];
527
+ fileLoadedComponents = []; // Components loaded from files
528
+ allComponents = []; // Combined list
290
529
  filteredComponents = [];
291
530
  selectedComponent = null;
292
531
  expandedComponent = null; // Track which card is expanded
@@ -296,6 +535,19 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
296
535
  isRunning = false; // Track if component is currently running
297
536
  // Error handling
298
537
  currentError = null;
538
+ // Tab management
539
+ activeTab = 0; // 0 = Spec, 1 = Code
540
+ // Splitter state
541
+ isDetailsPaneCollapsed = true; // Start with details collapsed
542
+ // Editor content
543
+ editableSpec = ''; // JSON string for spec editor
544
+ editableCode = ''; // JavaScript code for code editor
545
+ codeSections = [];
546
+ isEditingSpec = false;
547
+ isEditingCode = false;
548
+ lastEditSource = null;
549
+ // File input element reference
550
+ fileInput;
299
551
  destroy$ = new Subject();
300
552
  constructor(cdr) {
301
553
  super();
@@ -318,14 +570,14 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
318
570
  const rv = new RunView();
319
571
  const result = await rv.RunView({
320
572
  EntityName: 'MJ: Components',
321
- ExtraFilter: '',
573
+ ExtraFilter: 'HasCustomProps = 0', // Only load components without custom props
322
574
  OrderBy: 'Name',
323
575
  MaxRows: 1000,
324
576
  ResultType: 'entity_object'
325
577
  });
326
578
  if (result.Success) {
327
579
  this.components = result.Results || [];
328
- this.filterComponents();
580
+ this.combineAndFilterComponents();
329
581
  }
330
582
  else {
331
583
  console.error('Failed to load components:', result.ErrorMessage);
@@ -340,22 +592,67 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
340
592
  }
341
593
  onSearchChange(query) {
342
594
  this.searchQuery = query;
343
- this.filterComponents();
595
+ this.combineAndFilterComponents();
344
596
  }
345
- filterComponents() {
597
+ combineAndFilterComponents() {
598
+ // Combine database components with file-loaded components
599
+ this.allComponents = [
600
+ ...this.fileLoadedComponents,
601
+ ...this.components
602
+ ];
603
+ // Apply search filter
346
604
  if (!this.searchQuery) {
347
- this.filteredComponents = [...this.components];
605
+ this.filteredComponents = [...this.allComponents];
348
606
  }
349
607
  else {
350
608
  const query = this.searchQuery.toLowerCase();
351
- this.filteredComponents = this.components.filter(c => c.Name?.toLowerCase().includes(query) ||
352
- c.Description?.toLowerCase().includes(query) ||
353
- c.Type?.toLowerCase().includes(query));
609
+ this.filteredComponents = this.allComponents.filter(c => {
610
+ const name = this.getComponentName(c)?.toLowerCase() || '';
611
+ const description = this.getComponentDescription(c)?.toLowerCase() || '';
612
+ const type = this.getComponentType(c)?.toLowerCase() || '';
613
+ return name.includes(query) || description.includes(query) || type.includes(query);
614
+ });
354
615
  }
355
616
  }
617
+ // Helper methods to get properties from union type
618
+ getComponentName(component) {
619
+ return component.isFileLoaded ? component.name : component.Name;
620
+ }
621
+ getComponentDescription(component) {
622
+ return component.isFileLoaded ? component.description : (component.Description || undefined);
623
+ }
624
+ getComponentType(component) {
625
+ return component.isFileLoaded ? component.type : (component.Type || undefined);
626
+ }
627
+ getComponentStatus(component) {
628
+ return component.isFileLoaded ? component.status : (component.Status || undefined);
629
+ }
630
+ getComponentVersion(component) {
631
+ return component.isFileLoaded ? '1.0.0' : (component.Version || '1.0.0');
632
+ }
633
+ getComponentSpec(component) {
634
+ return component.isFileLoaded ? component.specification : JSON.parse(component.Specification);
635
+ }
636
+ getComponentId(component) {
637
+ return component.isFileLoaded ? component.id : component.ID;
638
+ }
639
+ isFileLoadedComponent(component) {
640
+ return component.isFileLoaded === true;
641
+ }
642
+ getComponentFilename(component) {
643
+ return component.isFileLoaded ? component.filename : undefined;
644
+ }
645
+ getComponentLoadedAt(component) {
646
+ return component.isFileLoaded ? component.loadedAt : undefined;
647
+ }
648
+ getComponentUpdatedAt(component) {
649
+ return !component.isFileLoaded && component.__mj_UpdatedAt ? component.__mj_UpdatedAt : undefined;
650
+ }
356
651
  toggleComponentExpansion(component) {
357
652
  // Toggle expansion - if clicking the same component, collapse it
358
- if (this.expandedComponent?.ID === component.ID) {
653
+ const componentId = this.getComponentId(component);
654
+ const expandedId = this.expandedComponent ? this.getComponentId(this.expandedComponent) : null;
655
+ if (expandedId === componentId) {
359
656
  this.expandedComponent = null;
360
657
  }
361
658
  else {
@@ -364,19 +661,43 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
364
661
  this.cdr.detectChanges();
365
662
  }
366
663
  runComponent(component) {
664
+ // If another component is running, stop it first then start the new one
665
+ const componentId = this.getComponentId(component);
666
+ const selectedId = this.selectedComponent ? this.getComponentId(this.selectedComponent) : null;
667
+ if (this.isRunning && selectedId !== componentId) {
668
+ this.stopComponent();
669
+ this.startComponent(component);
670
+ }
671
+ else {
672
+ this.startComponent(component);
673
+ }
674
+ }
675
+ startComponent(component) {
367
676
  this.selectedComponent = component;
368
- this.componentSpec = JSON.parse(component.Specification);
677
+ this.componentSpec = this.getComponentSpec(component);
369
678
  this.isRunning = true;
370
679
  this.currentError = null; // Clear any previous errors
371
- console.log('Running component:', component.Name);
372
- this.cdr.detectChanges();
680
+ this.isDetailsPaneCollapsed = true; // Start with details collapsed
681
+ this.initializeEditors(); // Initialize spec and code editors
682
+ console.log('Running component:', this.getComponentName(component));
683
+ try {
684
+ this.cdr.detectChanges();
685
+ }
686
+ catch (error) {
687
+ console.error('Error with cdr.detectChanges():', error);
688
+ }
373
689
  }
374
690
  stopComponent() {
375
691
  this.isRunning = false;
376
692
  this.selectedComponent = null;
377
693
  this.componentSpec = null;
378
694
  this.currentError = null;
379
- this.cdr.detectChanges();
695
+ try {
696
+ this.cdr.detectChanges();
697
+ }
698
+ catch (error) {
699
+ console.error('Error with cdr.detectChanges():', error);
700
+ }
380
701
  }
381
702
  /**
382
703
  * Handle component events from React components
@@ -421,7 +742,7 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
421
742
  const errorText = `
422
743
  Component Error Report
423
744
  ${'='.repeat(50)}
424
- Component: ${this.selectedComponent?.Name}
745
+ Component: ${this.selectedComponent ? this.getComponentName(this.selectedComponent) : 'Unknown'}
425
746
  Error Type: ${this.currentError.type}
426
747
  Message: ${this.currentError.message}
427
748
  ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify(this.currentError.technicalDetails, null, 2) : ''}
@@ -446,6 +767,81 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
446
767
  async refreshData() {
447
768
  await this.loadData();
448
769
  }
770
+ // File upload handling methods
771
+ triggerFileInput() {
772
+ this.fileInput?.nativeElement.click();
773
+ }
774
+ async handleFileSelect(event) {
775
+ const input = event.target;
776
+ const file = input.files?.[0];
777
+ if (!file)
778
+ return;
779
+ // Only accept JSON files
780
+ if (!file.name.endsWith('.json')) {
781
+ console.error('Please select a JSON file');
782
+ // Could add a toast notification here
783
+ return;
784
+ }
785
+ try {
786
+ const fileContent = await this.readFile(file);
787
+ const spec = JSON.parse(fileContent);
788
+ // Validate the spec has required fields
789
+ if (!spec.name || !spec.code) {
790
+ console.error('Invalid component specification: missing required fields (name, code)');
791
+ return;
792
+ }
793
+ // Create a file-loaded component
794
+ const fileComponent = {
795
+ id: this.generateId(),
796
+ name: spec.name,
797
+ description: spec.description,
798
+ specification: spec,
799
+ filename: file.name,
800
+ loadedAt: new Date(),
801
+ isFileLoaded: true,
802
+ type: spec.type || 'Component',
803
+ status: 'File'
804
+ };
805
+ // Add to the list and refresh
806
+ this.fileLoadedComponents.push(fileComponent);
807
+ this.combineAndFilterComponents();
808
+ console.log(`Loaded component "${spec.name}" from ${file.name}`);
809
+ // Automatically select and run the newly loaded component
810
+ this.expandedComponent = fileComponent;
811
+ this.runComponent(fileComponent);
812
+ // Clear the input for future uploads
813
+ input.value = '';
814
+ }
815
+ catch (error) {
816
+ console.error('Error loading component file:', error);
817
+ }
818
+ }
819
+ readFile(file) {
820
+ return new Promise((resolve, reject) => {
821
+ const reader = new FileReader();
822
+ reader.onload = (e) => resolve(e.target?.result);
823
+ reader.onerror = reject;
824
+ reader.readAsText(file);
825
+ });
826
+ }
827
+ generateId() {
828
+ return 'file-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
829
+ }
830
+ removeFileComponent(component) {
831
+ const index = this.fileLoadedComponents.indexOf(component);
832
+ if (index > -1) {
833
+ this.fileLoadedComponents.splice(index, 1);
834
+ // If this was the selected component, clear it
835
+ if (this.selectedComponent === component) {
836
+ this.stopComponent();
837
+ }
838
+ // If this was the expanded component, clear it
839
+ if (this.expandedComponent === component) {
840
+ this.expandedComponent = null;
841
+ }
842
+ this.combineAndFilterComponents();
843
+ }
844
+ }
449
845
  getComponentTypeIcon(type) {
450
846
  const icons = {
451
847
  'Report': 'fa-file-alt',
@@ -474,43 +870,286 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
474
870
  };
475
871
  return colors[type || ''] || '#9CA3AF';
476
872
  }
873
+ /**
874
+ * Initialize the spec and code editors when a component is selected
875
+ */
876
+ initializeEditors() {
877
+ if (this.selectedComponent) {
878
+ const spec = this.getComponentSpec(this.selectedComponent);
879
+ // Deep parse the spec for better readability
880
+ const parseOptions = {
881
+ extractInlineJson: true,
882
+ maxDepth: 100,
883
+ debug: false
884
+ };
885
+ const parsed = ParseJSONRecursive(spec, parseOptions);
886
+ this.editableSpec = JSON.stringify(parsed, null, 2);
887
+ // Extract code from spec
888
+ this.editableCode = spec.code || '// No code available';
889
+ // Build code sections array
890
+ this.buildCodeSections();
891
+ // Reset editing flags
892
+ this.isEditingSpec = false;
893
+ this.isEditingCode = false;
894
+ this.lastEditSource = null;
895
+ }
896
+ }
897
+ /**
898
+ * Handle spec editor changes
899
+ */
900
+ onSpecChange(newSpec) {
901
+ this.editableSpec = newSpec;
902
+ this.isEditingSpec = true;
903
+ this.lastEditSource = 'spec';
904
+ }
905
+ /**
906
+ * Handle code editor changes
907
+ */
908
+ onCodeChange(newCode) {
909
+ this.editableCode = newCode;
910
+ this.isEditingCode = true;
911
+ this.lastEditSource = 'code';
912
+ }
913
+ /**
914
+ * Apply spec changes and update the code tab
915
+ */
916
+ applySpecChanges() {
917
+ try {
918
+ const parsed = JSON.parse(this.editableSpec);
919
+ // Update the component spec
920
+ if (this.selectedComponent) {
921
+ if (this.isFileLoadedComponent(this.selectedComponent)) {
922
+ // Update file-loaded component
923
+ this.selectedComponent.specification = parsed;
924
+ }
925
+ else {
926
+ // Update database component's Specification field in memory only
927
+ this.selectedComponent.Specification = JSON.stringify(parsed);
928
+ }
929
+ // Update the runtime spec
930
+ this.componentSpec = parsed;
931
+ // Update the code editor with new code from spec
932
+ this.editableCode = parsed.code || '// No code available';
933
+ // Rebuild code sections from updated spec
934
+ this.buildCodeSections();
935
+ // If component is running, update it without full refresh
936
+ if (this.isRunning) {
937
+ this.updateRunningComponent();
938
+ }
939
+ this.isEditingSpec = false;
940
+ }
941
+ }
942
+ catch (error) {
943
+ console.error('Invalid JSON in spec editor:', error);
944
+ // Could show a toast notification here
945
+ }
946
+ }
947
+ /**
948
+ * Apply code changes and update the spec
949
+ */
950
+ applyCodeChanges() {
951
+ if (this.selectedComponent) {
952
+ try {
953
+ // Parse the current spec
954
+ const spec = JSON.parse(this.editableSpec);
955
+ // Update main code and dependencies from code sections
956
+ if (this.codeSections.length > 0) {
957
+ // First section is always the main component
958
+ spec.code = this.codeSections[0].code;
959
+ // Update dependencies if any
960
+ if (this.codeSections.length > 1 && spec.dependencies) {
961
+ for (let i = 1; i < this.codeSections.length; i++) {
962
+ const section = this.codeSections[i];
963
+ if (section.index !== undefined && spec.dependencies[section.index]) {
964
+ spec.dependencies[section.index].code = section.code;
965
+ }
966
+ }
967
+ }
968
+ }
969
+ // Update the spec editor
970
+ const parseOptions = {
971
+ extractInlineJson: true,
972
+ maxDepth: 100,
973
+ debug: false
974
+ };
975
+ const parsed = ParseJSONRecursive(spec, parseOptions);
976
+ this.editableSpec = JSON.stringify(parsed, null, 2);
977
+ // Update the component entity in memory
978
+ if (this.isFileLoadedComponent(this.selectedComponent)) {
979
+ this.selectedComponent.specification = spec;
980
+ }
981
+ else {
982
+ // Update database component's Specification field in memory only
983
+ this.selectedComponent.Specification = JSON.stringify(spec);
984
+ }
985
+ // Update the runtime spec
986
+ this.componentSpec = spec;
987
+ // If component is running, update it without full refresh
988
+ if (this.isRunning) {
989
+ this.updateRunningComponent();
990
+ }
991
+ this.isEditingCode = false;
992
+ }
993
+ catch (error) {
994
+ console.error('Error applying code changes:', error);
995
+ }
996
+ }
997
+ }
998
+ /**
999
+ * Refresh the running component with new spec/code (in-place update)
1000
+ */
1001
+ refreshComponent() {
1002
+ if (this.selectedComponent && this.isRunning) {
1003
+ // Use the same in-place update logic as Apply Changes
1004
+ this.updateRunningComponent();
1005
+ }
1006
+ }
1007
+ /**
1008
+ * Update the running component without full refresh
1009
+ */
1010
+ updateRunningComponent() {
1011
+ if (this.selectedComponent && this.isRunning) {
1012
+ // Get the updated spec
1013
+ const spec = this.getComponentSpec(this.selectedComponent);
1014
+ // Temporarily set to null to force React to re-render
1015
+ this.componentSpec = null;
1016
+ this.cdr.detectChanges();
1017
+ // Then set the new spec
1018
+ setTimeout(() => {
1019
+ this.componentSpec = spec;
1020
+ try {
1021
+ this.cdr.detectChanges();
1022
+ }
1023
+ catch (error) {
1024
+ console.error('Error with cdr.detectChanges():', error);
1025
+ }
1026
+ }, 10);
1027
+ }
1028
+ }
1029
+ /**
1030
+ * Build code sections array from spec
1031
+ */
1032
+ buildCodeSections() {
1033
+ if (!this.selectedComponent) {
1034
+ this.codeSections = [];
1035
+ return;
1036
+ }
1037
+ const spec = this.getComponentSpec(this.selectedComponent);
1038
+ const sections = [];
1039
+ // Main component code
1040
+ sections.push({
1041
+ title: spec.name || 'Main Component',
1042
+ code: spec.code || '// No code available',
1043
+ expanded: true,
1044
+ isDependency: false
1045
+ });
1046
+ // Add dependent components if any
1047
+ if (spec.dependencies && Array.isArray(spec.dependencies)) {
1048
+ spec.dependencies.forEach((dep, index) => {
1049
+ sections.push({
1050
+ title: dep.name || `Dependency ${index + 1}`,
1051
+ code: dep.code || '// No code available',
1052
+ expanded: false,
1053
+ isDependency: true,
1054
+ index: index
1055
+ });
1056
+ });
1057
+ }
1058
+ this.codeSections = sections;
1059
+ }
1060
+ /**
1061
+ * Get component code sections for panel bar
1062
+ */
1063
+ getComponentCodeSections() {
1064
+ return this.codeSections;
1065
+ }
1066
+ /**
1067
+ * Handle code section changes
1068
+ */
1069
+ onCodeSectionChange(newCode, sectionIndex) {
1070
+ if (this.codeSections[sectionIndex]) {
1071
+ this.codeSections[sectionIndex].code = newCode;
1072
+ this.isEditingCode = true;
1073
+ this.lastEditSource = 'code';
1074
+ }
1075
+ }
1076
+ /**
1077
+ * Toggle the details pane (spec/code editors)
1078
+ */
1079
+ toggleDetailsPane() {
1080
+ this.isDetailsPaneCollapsed = !this.isDetailsPaneCollapsed;
1081
+ this.cdr.detectChanges();
1082
+ }
1083
+ /**
1084
+ * Handle tab selection
1085
+ */
1086
+ onTabSelect(event) {
1087
+ this.activeTab = event.index;
1088
+ // Initialize editors when switching to spec or code tabs
1089
+ // Both tabs now need initialization since there's no separate Run tab
1090
+ this.initializeEditors();
1091
+ }
477
1092
  static ɵfac = function ComponentStudioDashboardComponent_Factory(t) { return new (t || ComponentStudioDashboardComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
478
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentStudioDashboardComponent, selectors: [["mj-component-studio-dashboard"]], features: [i0.ɵɵInheritDefinitionFeature], decls: 25, vars: 10, consts: [[1, "component-studio"], [1, "dashboard-header"], [1, "header-content"], [1, "fa-solid", "fa-puzzle-piece"], ["kendoButton", "", 3, "click", "icon", "disabled"], ["orientation", "horizontal", 2, "flex", "1", "height", "auto"], [3, "min", "max", "size"], [1, "components-panel"], [1, "panel-header"], [1, "search-box"], ["placeholder", "Search components...", 3, "valueChange", "value", "clearButton"], ["kendoTextBoxPrefixTemplate", ""], [1, "components-list"], [1, "loading-message"], [1, "empty-message"], [3, "min"], [1, "component-display"], [1, "empty-state"], [1, "fa-solid", "fa-search"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "component-card", 3, "expanded", "running"], [1, "component-card"], [1, "card-header", 3, "click"], [1, "card-icon"], [1, "fa-solid", 3, "ngClass"], [1, "card-info"], [1, "card-name"], [1, "card-meta"], [1, "card-type"], [1, "card-version"], [1, "status-badge", "published"], [1, "status-badge", "draft"], [1, "card-chevron"], [1, "fa-solid", "fa-chevron-up"], [1, "fa-solid", "fa-chevron-down"], [1, "card-details"], [1, "detail-section"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], [1, "card-actions"], ["kendoButton", "", 3, "icon", "themeColor"], ["kendoButton", "", 3, "click", "icon", "themeColor"], [1, "error-display"], [3, "component"], [1, "error-container"], [1, "error-header"], [1, "fa-solid", "fa-exclamation-triangle"], ["title", "Copy error details", 1, "copy-button", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "error-intro"], [1, "error-details"], [1, "technical-details"], [1, "error-help"], [1, "error-actions"], ["kendoButton", "", 3, "click", "icon"], [3, "componentEvent", "openEntityRecord", "component"], [1, "fa-solid", "fa-rocket", "fa-3x"]], template: function ComponentStudioDashboardComponent_Template(rf, ctx) { if (rf & 1) {
479
- i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "h1");
480
- i0.ɵɵelement(4, "i", 3);
481
- i0.ɵɵtext(5, " Component Studio");
1093
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentStudioDashboardComponent, selectors: [["mj-component-studio-dashboard"]], viewQuery: function ComponentStudioDashboardComponent_Query(rf, ctx) { if (rf & 1) {
1094
+ i0.ɵɵviewQuery(_c0, 5);
1095
+ } if (rf & 2) {
1096
+ let _t;
1097
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
1098
+ } }, features: [i0.ɵɵInheritDefinitionFeature], decls: 36, vars: 11, consts: [["fileInput", ""], [1, "component-studio"], [1, "dashboard-header"], [1, "header-content"], [1, "fa-solid", "fa-puzzle-piece"], [1, "header-subtitle"], [1, "header-buttons"], ["kendoButton", "", 3, "themeColor"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-file-import"], ["kendoButton", "", 3, "click", "disabled"], [1, "fa-solid", "fa-sync"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["orientation", "horizontal", 2, "flex", "1", "height", "auto"], [3, "min", "max", "size"], [1, "components-panel"], [1, "panel-header"], [1, "search-box"], ["placeholder", "Search components...", 3, "valueChange", "value", "clearButton"], ["kendoTextBoxPrefixTemplate", ""], [1, "components-list"], [1, "loading-message"], [1, "empty-message"], [3, "min"], [1, "component-display"], ["orientation", "horizontal", 1, "component-editor-splitter"], [1, "empty-state"], [1, "fa-solid", "fa-eye"], [1, "fa-solid", "fa-eye-slash"], [1, "fa-solid", "fa-search"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-info-circle"], [1, "component-card", 3, "expanded", "running", "file-loaded"], [1, "component-card"], [1, "card-header", 3, "click"], [1, "card-icon"], [1, "fa-solid", 3, "ngClass"], [1, "card-info"], [1, "card-name"], [1, "file-badge", 3, "title"], [1, "card-meta"], [1, "card-type"], [1, "card-version"], [1, "status-badge", "file"], [1, "status-badge", "published"], [1, "status-badge", "draft"], [1, "card-chevron"], [1, "fa-solid", "fa-chevron-up"], [1, "fa-solid", "fa-chevron-down"], [1, "card-details"], [1, "fa-solid", "fa-file"], [1, "detail-section"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], [1, "card-actions"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "themeColor"], [1, "fa-solid", "fa-stop"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "click", "themeColor"], [1, "fa-solid", "fa-play"], [3, "min", "collapsible", "size"], [1, "component-runtime"], [1, "run-empty-state"], [3, "min", "collapsible", "collapsed"], [1, "editor-tabs", 3, "tabSelect"], [3, "title", "selected"], ["kendoTabContent", ""], [1, "error-display"], [3, "component"], [1, "error-container"], [1, "error-header"], [1, "fa-solid", "fa-exclamation-triangle"], ["title", "Copy error details", 1, "copy-button", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "error-intro"], [1, "error-details"], [1, "technical-details"], [1, "error-help"], [1, "error-actions"], ["kendoButton", "", 3, "click"], [1, "fa-solid", "fa-rotate"], [3, "componentEvent", "openEntityRecord", "component"], [1, "fa-solid", "fa-play-circle", "fa-3x"], ["kendoButton", "", 3, "click", "themeColor", "size"], [1, "tab-content", "spec-tab"], [1, "editor-header"], [1, "fa-solid", "fa-code"], [1, "editor-actions"], [1, "editor-wrapper"], [2, "height", "100%", "width", "100%", 3, "ngModelChange", "ngModel", "language", "readonly"], [1, "fa-solid", "fa-check"], [1, "fa-solid", "fa-times"], [1, "tab-content", "code-tab"], [1, "fa-solid", "fa-file-code"], [1, "code-sections"], [3, "title", "expanded"], ["kendoPanelBarContent", ""], [2, "height", "400px", "width", "100%", 3, "ngModelChange", "ngModel", "language", "readonly"], [1, "fa-solid", "fa-rocket", "fa-3x"]], template: function ComponentStudioDashboardComponent_Template(rf, ctx) { if (rf & 1) {
1099
+ const _r1 = i0.ɵɵgetCurrentView();
1100
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div")(4, "h1");
1101
+ i0.ɵɵelement(5, "i", 4);
1102
+ i0.ɵɵtext(6, " Component Studio");
482
1103
  i0.ɵɵelementEnd();
483
- i0.ɵɵelementStart(6, "button", 4);
484
- i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Template_button_click_6_listener() { return ctx.refreshData(); });
485
- i0.ɵɵtext(7, " Refresh ");
1104
+ i0.ɵɵelementStart(7, "p", 5);
1105
+ i0.ɵɵtext(8, "Testing components without custom properties");
1106
+ i0.ɵɵelementEnd()();
1107
+ i0.ɵɵelementStart(9, "div", 6);
1108
+ i0.ɵɵtemplate(10, ComponentStudioDashboardComponent_Conditional_10_Template, 3, 2, "button", 7);
1109
+ i0.ɵɵelementStart(11, "button", 8);
1110
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Template_button_click_11_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.triggerFileInput()); });
1111
+ i0.ɵɵelement(12, "span", 9);
1112
+ i0.ɵɵtext(13, " Import from File ");
1113
+ i0.ɵɵelementEnd();
1114
+ i0.ɵɵelementStart(14, "button", 10);
1115
+ i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.refreshData()); });
1116
+ i0.ɵɵelement(15, "span", 11);
1117
+ i0.ɵɵtext(16, " Refresh ");
1118
+ i0.ɵɵelementEnd()();
1119
+ i0.ɵɵelementStart(17, "input", 12, 0);
1120
+ i0.ɵɵlistener("change", function ComponentStudioDashboardComponent_Template_input_change_17_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.handleFileSelect($event)); });
486
1121
  i0.ɵɵelementEnd()()();
487
- i0.ɵɵelementStart(8, "kendo-splitter", 5)(9, "kendo-splitter-pane", 6)(10, "div", 7)(11, "div", 8)(12, "h3");
488
- i0.ɵɵtext(13, "Components");
1122
+ i0.ɵɵelementStart(19, "kendo-splitter", 13)(20, "kendo-splitter-pane", 14)(21, "div", 15)(22, "div", 16)(23, "h3");
1123
+ i0.ɵɵtext(24, "Components");
489
1124
  i0.ɵɵelementEnd();
490
- i0.ɵɵelementStart(14, "div", 9)(15, "kendo-textbox", 10);
491
- i0.ɵɵlistener("valueChange", function ComponentStudioDashboardComponent_Template_kendo_textbox_valueChange_15_listener($event) { return ctx.onSearchChange($event); });
492
- i0.ɵɵtemplate(16, ComponentStudioDashboardComponent_ng_template_16_Template, 1, 0, "ng-template", 11);
1125
+ i0.ɵɵelementStart(25, "div", 17)(26, "kendo-textbox", 18);
1126
+ i0.ɵɵlistener("valueChange", function ComponentStudioDashboardComponent_Template_kendo_textbox_valueChange_26_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onSearchChange($event)); });
1127
+ i0.ɵɵtemplate(27, ComponentStudioDashboardComponent_ng_template_27_Template, 1, 0, "ng-template", 19);
493
1128
  i0.ɵɵelementEnd()()();
494
- i0.ɵɵelementStart(17, "div", 12);
495
- i0.ɵɵtemplate(18, ComponentStudioDashboardComponent_Conditional_18_Template, 3, 0, "div", 13)(19, ComponentStudioDashboardComponent_Conditional_19_Template, 2, 0, "div", 14)(20, ComponentStudioDashboardComponent_Conditional_20_Template, 2, 0);
1129
+ i0.ɵɵelementStart(28, "div", 20);
1130
+ i0.ɵɵtemplate(29, ComponentStudioDashboardComponent_Conditional_29_Template, 3, 0, "div", 21)(30, ComponentStudioDashboardComponent_Conditional_30_Template, 6, 0, "div", 22)(31, ComponentStudioDashboardComponent_Conditional_31_Template, 2, 0);
496
1131
  i0.ɵɵelementEnd()()();
497
- i0.ɵɵelementStart(21, "kendo-splitter-pane", 15)(22, "div", 16);
498
- i0.ɵɵtemplate(23, ComponentStudioDashboardComponent_Conditional_23_Template, 2, 1)(24, ComponentStudioDashboardComponent_Conditional_24_Template, 6, 0, "div", 17);
1132
+ i0.ɵɵelementStart(32, "kendo-splitter-pane", 23)(33, "div", 24);
1133
+ i0.ɵɵtemplate(34, ComponentStudioDashboardComponent_Conditional_34_Template, 11, 11, "kendo-splitter", 25)(35, ComponentStudioDashboardComponent_Conditional_35_Template, 6, 0, "div", 26);
499
1134
  i0.ɵɵelementEnd()()()();
500
1135
  } if (rf & 2) {
501
- i0.ɵɵadvance(6);
502
- i0.ɵɵproperty("icon", "fa-solid fa-sync")("disabled", ctx.isLoading);
1136
+ i0.ɵɵadvance(10);
1137
+ i0.ɵɵconditional(ctx.selectedComponent && ctx.isRunning ? 10 : -1);
1138
+ i0.ɵɵadvance();
1139
+ i0.ɵɵproperty("themeColor", "info");
503
1140
  i0.ɵɵadvance(3);
1141
+ i0.ɵɵproperty("disabled", ctx.isLoading);
1142
+ i0.ɵɵadvance(6);
504
1143
  i0.ɵɵproperty("min", "350px")("max", "600px")("size", "400px");
505
1144
  i0.ɵɵadvance(6);
506
1145
  i0.ɵɵproperty("value", ctx.searchQuery)("clearButton", true);
507
1146
  i0.ɵɵadvance(3);
508
- i0.ɵɵconditional(ctx.isLoading ? 18 : ctx.filteredComponents.length === 0 ? 19 : 20);
1147
+ i0.ɵɵconditional(ctx.isLoading ? 29 : ctx.filteredComponents.length === 0 ? 30 : 31);
509
1148
  i0.ɵɵadvance(3);
510
1149
  i0.ɵɵproperty("min", "400px");
511
1150
  i0.ɵɵadvance(2);
512
- i0.ɵɵconditional(ctx.isRunning && ctx.selectedComponent && ctx.componentSpec ? 23 : 24);
513
- } }, dependencies: [i1.NgClass, i2.TextBoxComponent, i2.TextBoxPrefixTemplateDirective, i3.SplitterComponent, i3.SplitterPaneComponent, i4.ButtonComponent, i5.MJReactComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n overflow: hidden;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] });
1151
+ i0.ɵɵconditional(ctx.selectedComponent ? 34 : 35);
1152
+ } }, dependencies: [i1.NgClass, i2.NgControlStatus, i2.NgModel, i3.TextBoxComponent, i3.TextBoxPrefixTemplateDirective, i4.PanelBarComponent, i4.PanelBarItemComponent, i4.PanelBarContentDirective, i4.SplitterComponent, i4.SplitterPaneComponent, i4.TabStripComponent, i4.TabStripTabComponent, i4.TabContentDirective, i5.CodeEditorComponent, i6.ButtonComponent, i7.MJReactComponent, i1.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n \n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] });
514
1153
  };
515
1154
  ComponentStudioDashboardComponent = __decorate([
516
1155
  RegisterClass(BaseDashboard, 'ComponentStudioDashboard')
@@ -518,9 +1157,12 @@ ComponentStudioDashboardComponent = __decorate([
518
1157
  export { ComponentStudioDashboardComponent };
519
1158
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentStudioDashboardComponent, [{
520
1159
  type: Component,
521
- args: [{ selector: 'mj-component-studio-dashboard', template: "<div class=\"component-studio\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-content\">\n <h1><i class=\"fa-solid fa-puzzle-piece\"></i> Component Studio</h1>\n <button kendoButton [icon]=\"'fa-solid fa-sync'\" (click)=\"refreshData()\" [disabled]=\"isLoading\">\n Refresh\n </button>\n </div>\n </div>\n\n <!-- Main Content with Splitter -->\n <kendo-splitter orientation=\"horizontal\" style=\"flex: 1; height: auto;\">\n <!-- Left Panel - Component List -->\n <kendo-splitter-pane [min]=\"'350px'\" [max]=\"'600px'\" [size]=\"'400px'\">\n <div class=\"components-panel\">\n <div class=\"panel-header\">\n <h3>Components</h3>\n <div class=\"search-box\">\n <kendo-textbox \n [value]=\"searchQuery\"\n (valueChange)=\"onSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n </div>\n \n <div class=\"components-list\">\n @if (isLoading) {\n <div class=\"loading-message\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading components...\n </div>\n } @else if (filteredComponents.length === 0) {\n <div class=\"empty-message\">\n No components found\n </div>\n } @else {\n @for (component of filteredComponents; track component.ID) {\n <div class=\"component-card\" \n [class.expanded]=\"expandedComponent?.ID === component.ID\"\n [class.running]=\"selectedComponent?.ID === component.ID && isRunning\">\n \n <!-- Card Header - Always visible -->\n <div class=\"card-header\" (click)=\"toggleComponentExpansion(component)\">\n <div class=\"card-icon\" [style.color]=\"getComponentTypeColor(component.Type)\">\n <i class=\"fa-solid\" [ngClass]=\"getComponentTypeIcon(component.Type)\"></i>\n </div>\n <div class=\"card-info\">\n <div class=\"card-name\">{{ component.Name }}</div>\n <div class=\"card-meta\">\n <span class=\"card-type\">{{ component.Type || 'Component' }}</span>\n <span class=\"card-version\">v{{ component.Version || '1.0.0' }}</span>\n @if (component.Status === 'Published') {\n <span class=\"status-badge published\">Published</span>\n } @else {\n <span class=\"status-badge draft\">Draft</span>\n }\n </div>\n </div>\n <div class=\"card-chevron\">\n @if (expandedComponent?.ID === component.ID) {\n <i class=\"fa-solid fa-chevron-up\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </div>\n </div>\n \n <!-- Card Details - Only visible when expanded -->\n @if (expandedComponent?.ID === component.ID) {\n <div class=\"card-details\">\n @if (component.Description) {\n <div class=\"detail-section\">\n <label>Description</label>\n <p>{{ component.Description }}</p>\n </div>\n }\n \n <div class=\"detail-section\">\n <label>Component Info</label>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type:</span>\n <span class=\"info-value\">{{ component.Type || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version:</span>\n <span class=\"info-value\">{{ component.Version || '1.0.0' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status:</span>\n <span class=\"info-value\">{{ component.Status || 'Draft' }}</span>\n </div>\n @if (component.__mj_UpdatedAt) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated:</span>\n <span class=\"info-value\">{{ component.__mj_UpdatedAt | date:'short' }}</span>\n </div>\n }\n </div>\n </div>\n \n <div class=\"card-actions\">\n @if (selectedComponent?.ID === component.ID && isRunning) {\n <button kendoButton \n [icon]=\"'fa-solid fa-stop'\" \n [themeColor]=\"'error'\"\n (click)=\"stopComponent(); $event.stopPropagation()\">\n Stop Component\n </button>\n } @else {\n <button kendoButton \n [icon]=\"'fa-solid fa-play'\" \n [themeColor]=\"'primary'\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n Run Component\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </kendo-splitter-pane>\n\n <!-- Right Panel - Component Display -->\n <kendo-splitter-pane [min]=\"'400px'\">\n <div class=\"component-display\">\n @if (isRunning && selectedComponent && componentSpec) {\n @if (currentError) {\n <!-- Error Display -->\n <div class=\"error-display\">\n <div class=\"error-container\">\n <div class=\"error-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>Component Error</h3>\n <button class=\"copy-button\" (click)=\"copyErrorToClipboard()\" title=\"Copy error details\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n \n <p class=\"error-intro\">\n The component could not be rendered due to the following error:\n </p>\n \n <div class=\"error-details\">\n <strong>Error Type:</strong> {{ currentError.type }}<br>\n <strong>Message:</strong> {{ currentError.message }}\n @if (currentError.technicalDetails) {\n <details class=\"technical-details\">\n <summary>Technical Details (click to expand)</summary>\n <pre>{{ formatTechnicalDetails(currentError.technicalDetails) }}</pre>\n </details>\n }\n </div>\n \n <div class=\"error-help\">\n <strong>What to do:</strong>\n <ol>\n <li>Check that the component code is valid JavaScript/React</li>\n <li>Ensure all required dependencies are available</li>\n <li>Review the technical details for specific error information</li>\n <li>Contact your system administrator if the issue persists</li>\n </ol>\n </div>\n \n <div class=\"error-actions\">\n <button kendoButton (click)=\"retryComponent()\" [icon]=\"'fa-solid fa-rotate'\">\n Retry\n </button>\n <button kendoButton (click)=\"stopComponent()\" [icon]=\"'fa-solid fa-stop'\" [themeColor]=\"'error'\">\n Stop\n </button>\n </div>\n </div>\n </div>\n } @else {\n <!-- React Component -->\n <mj-react-component \n [component]=\"componentSpec\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-react-component>\n }\n } @else {\n <!-- Empty State -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-rocket fa-3x\"></i>\n <h2>Ready to Test Components</h2>\n <p>Select a component from the list and click \"Run Component\" to see it in action</p>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div>", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: #f8f9fa;\n overflow: hidden;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n }\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] }]
522
- }], () => [{ type: i0.ChangeDetectorRef }], null); })();
523
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentStudioDashboardComponent, { className: "ComponentStudioDashboardComponent", filePath: "src/ComponentStudio/component-studio-dashboard.component.ts", lineNumber: 18 }); })();
1160
+ args: [{ selector: 'mj-component-studio-dashboard', template: "<div class=\"component-studio\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-content\">\n <div>\n <h1><i class=\"fa-solid fa-puzzle-piece\"></i> Component Studio</h1>\n <p class=\"header-subtitle\">Testing components without custom properties</p>\n </div>\n <div class=\"header-buttons\">\n @if (selectedComponent && isRunning) {\n <button kendoButton (click)=\"toggleDetailsPane()\" [themeColor]=\"'base'\">\n @if (isDetailsPaneCollapsed) {\n <span class=\"fa-solid fa-eye\"></span> Show Details\n } @else {\n <span class=\"fa-solid fa-eye-slash\"></span> Hide Details\n }\n </button>\n }\n <button kendoButton (click)=\"triggerFileInput()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-file-import\"></span> Import from File\n </button>\n <button kendoButton (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <span class=\"fa-solid fa-sync\"></span> Refresh\n </button>\n </div>\n <!-- Hidden file input -->\n <input #fileInput type=\"file\" accept=\".json\" (change)=\"handleFileSelect($event)\" style=\"display: none;\" />\n </div>\n </div>\n\n <!-- Main Content with Splitter -->\n <kendo-splitter orientation=\"horizontal\" style=\"flex: 1; height: auto;\">\n <!-- Left Panel - Component List -->\n <kendo-splitter-pane [min]=\"'350px'\" [max]=\"'600px'\" [size]=\"'400px'\">\n <div class=\"components-panel\">\n <div class=\"panel-header\">\n <h3>Components</h3>\n <div class=\"search-box\">\n <kendo-textbox \n [value]=\"searchQuery\"\n (valueChange)=\"onSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n </div>\n \n <div class=\"components-list\">\n @if (isLoading) {\n <div class=\"loading-message\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading components...\n </div>\n } @else if (filteredComponents.length === 0) {\n <div class=\"empty-message\">\n <i class=\"fa-solid fa-info-circle\"></i> No components found without custom properties.\n <br>\n <small>Only components that don't require custom props can be tested here.</small>\n </div>\n } @else {\n @for (component of filteredComponents; track getComponentId(component)) {\n <div class=\"component-card\" \n [class.expanded]=\"expandedComponent && getComponentId(expandedComponent) === getComponentId(component)\"\n [class.running]=\"selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning\"\n [class.file-loaded]=\"isFileLoadedComponent(component)\">\n \n <!-- Card Header - Always visible -->\n <div class=\"card-header\" (click)=\"toggleComponentExpansion(component)\">\n <div class=\"card-icon\" [style.color]=\"getComponentTypeColor(getComponentType(component))\">\n <i class=\"fa-solid\" [ngClass]=\"getComponentTypeIcon(getComponentType(component))\"></i>\n </div>\n <div class=\"card-info\">\n <div class=\"card-name\">\n {{ getComponentName(component) }}\n @if (isFileLoadedComponent(component)) {\n <span class=\"file-badge\" title=\"Loaded from {{ getComponentFilename(component) }}\">\n <i class=\"fa-solid fa-file\"></i> {{ getComponentFilename(component) }}\n </span>\n }\n </div>\n <div class=\"card-meta\">\n <span class=\"card-type\">{{ getComponentType(component) || 'Component' }}</span>\n <span class=\"card-version\">v{{ getComponentVersion(component) }}</span>\n @if (isFileLoadedComponent(component)) {\n <span class=\"status-badge file\">File</span>\n } @else if (getComponentStatus(component) === 'Published') {\n <span class=\"status-badge published\">Published</span>\n } @else {\n <span class=\"status-badge draft\">Draft</span>\n }\n </div>\n </div>\n <div class=\"card-chevron\">\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <i class=\"fa-solid fa-chevron-up\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </div>\n </div>\n \n <!-- Card Details - Only visible when expanded -->\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <div class=\"card-details\">\n @if (getComponentDescription(component)) {\n <div class=\"detail-section\">\n <label>Description</label>\n <p>{{ getComponentDescription(component) }}</p>\n </div>\n }\n \n <div class=\"detail-section\">\n <label>Component Info</label>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type:</span>\n <span class=\"info-value\">{{ getComponentType(component) || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version:</span>\n <span class=\"info-value\">{{ getComponentVersion(component) }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status:</span>\n <span class=\"info-value\">{{ getComponentStatus(component) || 'Draft' }}</span>\n </div>\n @if (isFileLoadedComponent(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Loaded:</span>\n <span class=\"info-value\">{{ getComponentLoadedAt(component) | date:'short' }}</span>\n </div>\n } @else if (!isFileLoadedComponent(component) && getComponentUpdatedAt(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated:</span>\n <span class=\"info-value\">{{ getComponentUpdatedAt(component) | date:'short' }}</span>\n </div>\n }\n </div>\n </div>\n \n <div class=\"card-actions\">\n @if (selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning) {\n <button kendoButton \n [themeColor]=\"'error'\"\n (click)=\"stopComponent(); $event.stopPropagation()\">\n <span class=\"fa-solid fa-stop\"></span> Stop Component\n </button>\n } @else if (isRunning && selectedComponent && getComponentId(selectedComponent) !== getComponentId(component)) {\n <button kendoButton \n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Switch to This Component\n </button>\n } @else {\n <button kendoButton \n [themeColor]=\"'primary'\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </kendo-splitter-pane>\n\n <!-- Right Panel - Component Display with Editor Splitter -->\n <kendo-splitter-pane [min]=\"'400px'\">\n <div class=\"component-display\">\n @if (selectedComponent) {\n <!-- Splitter for component and editors -->\n <kendo-splitter orientation=\"horizontal\" class=\"component-editor-splitter\">\n <!-- Left side - Running Component -->\n <kendo-splitter-pane [min]=\"'300px'\" [collapsible]=\"false\" [size]=\"isDetailsPaneCollapsed ? '100%' : '50%'\">\n <div class=\"component-runtime\">\n @if (isRunning && componentSpec) {\n @if (currentError) {\n <!-- Error Display -->\n <div class=\"error-display\">\n <div class=\"error-container\">\n <div class=\"error-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>Component Error</h3>\n <button class=\"copy-button\" (click)=\"copyErrorToClipboard()\" title=\"Copy error details\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n \n <p class=\"error-intro\">\n The component could not be rendered due to the following error:\n </p>\n \n <div class=\"error-details\">\n <strong>Error Type:</strong> {{ currentError.type }}<br>\n <strong>Message:</strong> {{ currentError.message }}\n @if (currentError.technicalDetails) {\n <details class=\"technical-details\">\n <summary>Technical Details (click to expand)</summary>\n <pre>{{ formatTechnicalDetails(currentError.technicalDetails) }}</pre>\n </details>\n }\n </div>\n \n <div class=\"error-help\">\n <strong>What to do:</strong>\n <ol>\n <li>Check that the component code is valid JavaScript/React</li>\n <li>Ensure all required dependencies are available</li>\n <li>Review the technical details for specific error information</li>\n <li>Contact your system administrator if the issue persists</li>\n </ol>\n </div>\n \n <div class=\"error-actions\">\n <button kendoButton (click)=\"retryComponent()\">\n <span class=\"fa-solid fa-rotate\"></span> Retry\n </button>\n <button kendoButton (click)=\"stopComponent()\" [themeColor]=\"'error'\">\n <span class=\"fa-solid fa-stop\"></span> Stop\n </button>\n </div>\n </div>\n </div>\n } @else {\n <!-- React Component -->\n <mj-react-component \n [component]=\"componentSpec\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-react-component>\n }\n } @else {\n <!-- Component Not Running State -->\n <div class=\"run-empty-state\">\n <i class=\"fa-solid fa-play-circle fa-3x\"></i>\n <h3>Component: {{ getComponentName(selectedComponent) }}</h3>\n <p>{{ getComponentDescription(selectedComponent) || 'No description available' }}</p>\n <button kendoButton [themeColor]=\"'primary'\" [size]=\"'large'\" (click)=\"runComponent(selectedComponent)\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n \n <!-- Right side - Spec and Code Editors -->\n <kendo-splitter-pane [min]=\"'400px'\" [collapsible]=\"true\" [collapsed]=\"isDetailsPaneCollapsed\">\n <kendo-tabstrip (tabSelect)=\"onTabSelect($event)\" class=\"editor-tabs\">\n <!-- Spec Tab -->\n <kendo-tabstrip-tab [title]=\"'Spec'\" [selected]=\"activeTab === 0\">\n <ng-template kendoTabContent>\n <div class=\"tab-content spec-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-code\"></i> Component Specification (JSON)</h4>\n <div class=\"editor-actions\">\n @if (isEditingSpec) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applySpecChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n <div class=\"editor-wrapper\">\n <mj-code-editor\n [(ngModel)]=\"editableSpec\"\n (ngModelChange)=\"onSpecChange($event)\"\n [language]=\"'json'\"\n [readonly]=\"false\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n \n <!-- Code Tab -->\n <kendo-tabstrip-tab [title]=\"'Code'\" [selected]=\"activeTab === 1\">\n <ng-template kendoTabContent>\n <div class=\"tab-content code-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-file-code\"></i> Component Code (JavaScript/React)</h4>\n <div class=\"editor-actions\">\n @if (isEditingCode) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applyCodeChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n \n <!-- Always use panel bar for consistency and to show all components -->\n <div class=\"editor-wrapper\">\n <kendo-panelbar class=\"code-sections\">\n @for (section of getComponentCodeSections(); track section.title; let i = $index) {\n <kendo-panelbar-item [title]=\"section.title\" [expanded]=\"section.expanded\">\n <ng-template kendoPanelBarContent>\n <mj-code-editor\n [ngModel]=\"section.code\"\n (ngModelChange)=\"onCodeSectionChange($event, i)\"\n [language]=\"'javascript'\"\n [readonly]=\"false\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n </ng-template>\n </kendo-panelbar-item>\n }\n </kendo-panelbar>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n </kendo-tabstrip>\n </kendo-splitter-pane>\n </kendo-splitter>\n } @else {\n <!-- Empty State when no component selected -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-rocket fa-3x\"></i>\n <h2>Ready to Test Components</h2>\n <p>Select a component from the list to view its details and run it</p>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div>", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 18px;\n font-weight: 600;\n color: #212529;\n }\n \n .search-box {\n kendo-textbox {\n width: 100%;\n }\n }\n }\n \n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n \n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}"] }]
1161
+ }], () => [{ type: i0.ChangeDetectorRef }], { fileInput: [{
1162
+ type: ViewChild,
1163
+ args: ['fileInput', { static: false }]
1164
+ }] }); })();
1165
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentStudioDashboardComponent, { className: "ComponentStudioDashboardComponent", filePath: "src/ComponentStudio/component-studio-dashboard.component.ts", lineNumber: 35 }); })();
524
1166
  /**
525
1167
  * Function to prevent tree shaking of the ComponentStudioDashboardComponent.
526
1168
  */